mirror of
https://github.com/OrcaSlicer/OrcaSlicer.git
synced 2026-09-29 20:01:26 +00:00
Merge branch 'main' into publish_3mf
This commit is contained in:
+72
-7
@@ -370,13 +370,13 @@ if "%use_ninja%" == "ON" (
|
|||||||
set "using_ninja=ON"
|
set "using_ninja=ON"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
call :resolve_clang_cl
|
||||||
|
%repeat_error%
|
||||||
|
|
||||||
if "%using_ninja%" == "ON" (
|
if "%using_ninja%" == "ON" (
|
||||||
if "%use_clang_cl%" == "ON" (
|
if "%use_clang_cl%" == "ON" (
|
||||||
REM Bare, so it resolves from the PATH the dev shell just set up, which
|
REM Quoted, because the resolved path has spaces in it.
|
||||||
REM is the clang shipped with Visual Studio. --clang-path names another.
|
set "gen_args=-DCMAKE_C_COMPILER="!clang_exe!" -DCMAKE_CXX_COMPILER="!clang_exe!""
|
||||||
set "clang_exe=clang-cl.exe"
|
|
||||||
if not "%clang_path%" == "" set "clang_exe="%clang_path%""
|
|
||||||
set "gen_args=-DCMAKE_C_COMPILER=!clang_exe! -DCMAKE_CXX_COMPILER=!clang_exe!"
|
|
||||||
)
|
)
|
||||||
) else (
|
) else (
|
||||||
set "gen_args=-A !arch!"
|
set "gen_args=-A !arch!"
|
||||||
@@ -473,6 +473,7 @@ REM forward slashes, and anything that prints the directory has to show a
|
|||||||
REM real path rather than one glued onto the repository root.
|
REM real path rather than one glued onto the repository root.
|
||||||
for %%p in ("!build_dir!") do set "build_full=%%~fp"
|
for %%p in ("!build_dir!") do set "build_full=%%~fp"
|
||||||
echo Configuration: %build_type%, %arch%
|
echo Configuration: %build_type%, %arch%
|
||||||
|
if not "%clang_exe%" == "" echo Compiler: %clang_exe%
|
||||||
|
|
||||||
set "SIG_FLAG="
|
set "SIG_FLAG="
|
||||||
if defined ORCA_UPDATER_SIG_KEY set "SIG_FLAG=-DORCA_UPDATER_SIG_KEY=%ORCA_UPDATER_SIG_KEY%"
|
if defined ORCA_UPDATER_SIG_KEY set "SIG_FLAG=-DORCA_UPDATER_SIG_KEY=%ORCA_UPDATER_SIG_KEY%"
|
||||||
@@ -734,6 +735,14 @@ REM worked out the same way in either run.
|
|||||||
set "slicer_exe=%build_dir%\src\%build_type%\orca-slicer.exe"
|
set "slicer_exe=%build_dir%\src\%build_type%\orca-slicer.exe"
|
||||||
if "%install_slicer%" == "ON" set "slicer_exe=%build_dir%\OrcaSlicer\orca-slicer.exe"
|
if "%install_slicer%" == "ON" set "slicer_exe=%build_dir%\OrcaSlicer\orca-slicer.exe"
|
||||||
for %%p in ("!slicer_exe!") do set "slicer_full=%%~fp"
|
for %%p in ("!slicer_exe!") do set "slicer_full=%%~fp"
|
||||||
|
REM The 2026 generator writes OrcaSlicer.slnx, the releases before it
|
||||||
|
REM OrcaSlicer.sln. A file already there wins, in case an older CMake
|
||||||
|
REM configured the build.
|
||||||
|
set "solution=OrcaSlicer.sln"
|
||||||
|
if "%vs_version%" == "2026" set "solution=OrcaSlicer.slnx"
|
||||||
|
if exist "!build_full!\OrcaSlicer.sln" set "solution=OrcaSlicer.sln"
|
||||||
|
if exist "!build_full!\OrcaSlicer.slnx" set "solution=OrcaSlicer.slnx"
|
||||||
|
|
||||||
REM Naming a target builds it and its dependencies, not its dependents,
|
REM Naming a target builds it and its dependencies, not its dependents,
|
||||||
REM so only a full build or the executable's own target relinks.
|
REM so only a full build or the executable's own target relinks.
|
||||||
set "linked=ON"
|
set "linked=ON"
|
||||||
@@ -751,14 +760,14 @@ REM worked out the same way in either run.
|
|||||||
if "%build_deps%" == "ON" echo Dependencies !dep_full!
|
if "%build_deps%" == "ON" echo Dependencies !dep_full!
|
||||||
if "%build_slicer%" == "ON" if "%linked%" == "ON" echo OrcaSlicer !slicer_full!
|
if "%build_slicer%" == "ON" if "%linked%" == "ON" echo OrcaSlicer !slicer_full!
|
||||||
if "%build_slicer%" == "ON" if not "%linked%" == "ON" echo Target %slicer_target%
|
if "%build_slicer%" == "ON" if not "%linked%" == "ON" echo Target %slicer_target%
|
||||||
if "%build_slicer%" == "ON" if not "%using_ninja%" == "ON" echo Solution %build_full%\OrcaSlicer.sln
|
if "%build_slicer%" == "ON" if not "%using_ninja%" == "ON" echo Solution %build_full%\!solution!
|
||||||
if "%pack_deps%" == "ON" if defined bundle echo Bundle !bundle!
|
if "%pack_deps%" == "ON" if defined bundle echo Bundle !bundle!
|
||||||
|
|
||||||
echo.
|
echo.
|
||||||
echo Next
|
echo Next
|
||||||
if "%build_slicer%" == "ON" (
|
if "%build_slicer%" == "ON" (
|
||||||
if "%linked%" == "ON" echo Run it !slicer_exe!
|
if "%linked%" == "ON" echo Run it !slicer_exe!
|
||||||
if not "%using_ninja%" == "ON" echo Open in Visual Studio %build_dir%\OrcaSlicer.sln
|
if not "%using_ninja%" == "ON" echo Open in Visual Studio %build_dir%\!solution!
|
||||||
if "%linked%" == "ON" echo Rebuild after edits build_win.bat -s!recall! --no-configure
|
if "%linked%" == "ON" echo Rebuild after edits build_win.bat -s!recall! --no-configure
|
||||||
if not "%linked%" == "ON" echo Relink the binary build_win.bat -s!recall! --no-configure
|
if not "%linked%" == "ON" echo Relink the binary build_win.bat -s!recall! --no-configure
|
||||||
if "%linked%" == "ON" if "%using_ninja%" == "ON" echo Rebuild one target build_win.bat -s!recall! --no-configure --slicer-target libslic3r
|
if "%linked%" == "ON" if "%using_ninja%" == "ON" echo Rebuild one target build_win.bat -s!recall! --no-configure --slicer-target libslic3r
|
||||||
@@ -1080,6 +1089,62 @@ REM echo_var <variable>
|
|||||||
|
|
||||||
exit /b 0
|
exit /b 0
|
||||||
|
|
||||||
|
REM resolve_clang_cl - set clang_exe to the clang-cl a Ninja build uses.
|
||||||
|
REM VsDevCmd appends the Visual Studio LLVM directory to the end of PATH,
|
||||||
|
REM so a standalone LLVM already there shadows it. Name a full path.
|
||||||
|
:resolve_clang_cl
|
||||||
|
set "clang_exe="
|
||||||
|
if not "%using_ninja%" == "ON" exit /b 0
|
||||||
|
if not "%use_clang_cl%" == "ON" exit /b 0
|
||||||
|
REM Only a configure uses it, so -p and --no-configure need none.
|
||||||
|
if "%no_configure%" == "ON" exit /b 0
|
||||||
|
if "%build_deps%%build_slicer%" == "" exit /b 0
|
||||||
|
|
||||||
|
REM --clang-path wins. Forward slashes either way, so CMake does not
|
||||||
|
REM read a backslash as an escape.
|
||||||
|
if not "%clang_path%" == "" (
|
||||||
|
set "clang_exe=%clang_path:\=/%"
|
||||||
|
exit /b 0
|
||||||
|
)
|
||||||
|
|
||||||
|
setlocal
|
||||||
|
|
||||||
|
REM Keyed on the host, not %arch%, because the x64 compiler
|
||||||
|
REM cross-compiles to ARM64.
|
||||||
|
set "llvm_host=x64"
|
||||||
|
if /I "%PROCESSOR_ARCHITECTURE%" == "ARM64" set "llvm_host=ARM64"
|
||||||
|
|
||||||
|
set "found="
|
||||||
|
%VSWHERE% -nologo >nul 2>nul
|
||||||
|
if !errorlevel! == 0 (
|
||||||
|
for /f "tokens=*" %%i in ('%VSWHERE% -nologo -products * -latest -property resolvedInstallationPath') do (
|
||||||
|
if exist "%%i\VC\Tools\Llvm\!llvm_host!\bin\clang-cl.exe" (
|
||||||
|
set "found=%%i\VC\Tools\Llvm\!llvm_host!\bin\clang-cl.exe"
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
REM No clang toolset in Visual Studio. where lists every match, and the
|
||||||
|
REM first is the one PATH would resolve.
|
||||||
|
if "!found!" == "" (
|
||||||
|
for /f "tokens=*" %%i in ('where clang-cl.exe 2^>nul') do (
|
||||||
|
if "!found!" == "" set "found=%%i"
|
||||||
|
)
|
||||||
|
if not "!found!" == "" echo Visual Studio has no clang-cl; using !found! from PATH.
|
||||||
|
)
|
||||||
|
|
||||||
|
if "!found!" == "" (
|
||||||
|
echo No clang-cl found. Add the C++ Clang Compiler component with
|
||||||
|
echo %script_name% --install-vs ide -l
|
||||||
|
echo or name a standalone one with --clang-path.
|
||||||
|
endlocal
|
||||||
|
exit /b 1
|
||||||
|
)
|
||||||
|
|
||||||
|
endlocal & set "clang_exe=%found:\=/%"
|
||||||
|
|
||||||
|
exit /b 0
|
||||||
|
|
||||||
REM clean_tree <path> - remove a build tree, refusing anything that is not
|
REM clean_tree <path> - remove a build tree, refusing anything that is not
|
||||||
REM one. Nothing here should ever fire; it is a floor under a bug that
|
REM one. Nothing here should ever fire; it is a floor under a bug that
|
||||||
REM produced a path far shorter than it looks.
|
REM produced a path far shorter than it looks.
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "Snapmaker",
|
"name": "Snapmaker",
|
||||||
"version": "02.04.00.09",
|
"version": "02.04.00.10",
|
||||||
"force_update": "0",
|
"force_update": "0",
|
||||||
"description": "Snapmaker configurations",
|
"description": "Snapmaker configurations",
|
||||||
"machine_model_list": [
|
"machine_model_list": [
|
||||||
|
|||||||
@@ -184,7 +184,7 @@
|
|||||||
"nozzle_type": "undefine",
|
"nozzle_type": "undefine",
|
||||||
"auxiliary_fan": "0",
|
"auxiliary_fan": "0",
|
||||||
"support_multi_bed_types": "1",
|
"support_multi_bed_types": "1",
|
||||||
"default_bed_type": "4",
|
"default_bed_type": "Textured PEI Plate",
|
||||||
"printable_area": [
|
"printable_area": [
|
||||||
"0.5x1",
|
"0.5x1",
|
||||||
"270.5x1",
|
"270.5x1",
|
||||||
|
|||||||
+70
-10
@@ -85,6 +85,24 @@ foreach ($v in @{ old = '1.11.1'; new = '1.12.0' }.GetEnumerator()) {
|
|||||||
$ninjaPaths[$v.Key] = "$d;$env:PATH"
|
$ninjaPaths[$v.Key] = "$d;$env:PATH"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# A clang-cl earlier on PATH than the Visual Studio one, which is what the
|
||||||
|
# compiler used to resolve to. Nothing runs it; the script only locates it.
|
||||||
|
$clangDir = Join-Path $fixtures 'clang'
|
||||||
|
New-Item -ItemType Directory -Force -Path $clangDir | Out-Null
|
||||||
|
Copy-Item "$env:SystemRoot\System32\where.exe" (Join-Path $clangDir 'clang-cl.exe') -Force
|
||||||
|
$clangOnPath = "$clangDir;$env:PATH"
|
||||||
|
|
||||||
|
# ProgramFiles(x86) is where the script looks for vswhere, so an empty one
|
||||||
|
# stands in for a machine whose Visual Studio has no clang toolset.
|
||||||
|
$noVs = Join-Path $fixtures 'no-vs'
|
||||||
|
New-Item -ItemType Directory -Force -Path $noVs | Out-Null
|
||||||
|
|
||||||
|
# A build directory that already holds a classic solution, for the case where
|
||||||
|
# what is on disk disagrees with what the generator would write.
|
||||||
|
$slnDir = Join-Path $fixtures 'sln'
|
||||||
|
New-Item -ItemType Directory -Force -Path $slnDir | Out-Null
|
||||||
|
Set-Content -Path (Join-Path $slnDir 'OrcaSlicer.sln') -Value '' -Encoding ascii
|
||||||
|
|
||||||
# The pack stamp is checked against real dates, so a locale-dependent parse
|
# The pack stamp is checked against real dates, so a locale-dependent parse
|
||||||
# in the script cannot pass by looking date-shaped. Yesterday is accepted too,
|
# in the script cannot pass by looking date-shaped. Yesterday is accepted too,
|
||||||
# so a run that crosses midnight does not flake.
|
# so a run that crosses midnight does not flake.
|
||||||
@@ -131,7 +149,36 @@ $cases = @(
|
|||||||
Contains = @('-G "Ninja Multi-Config"')
|
Contains = @('-G "Ninja Multi-Config"')
|
||||||
NotContains = @('clang-cl', '-A x64') }
|
NotContains = @('clang-cl', '-A x64') }
|
||||||
@{ Name = '-l -x builds with clang-cl under Ninja'; Args = @('-d', '-l', '-x')
|
@{ Name = '-l -x builds with clang-cl under Ninja'; Args = @('-d', '-l', '-x')
|
||||||
Contains = @('-G "Ninja Multi-Config"', '-DCMAKE_C_COMPILER=clang-cl.exe', '-DCMAKE_CXX_COMPILER=clang-cl.exe') }
|
Contains = @('-G "Ninja Multi-Config"')
|
||||||
|
Match = @('-DCMAKE_C_COMPILER="[^"]+/clang-cl\.exe"', '-DCMAKE_CXX_COMPILER="[^"]+/clang-cl\.exe"') }
|
||||||
|
# PATH order used to decide the compiler. VsDevCmd appends the Visual
|
||||||
|
# Studio LLVM directory to the end of PATH, so a standalone LLVM already
|
||||||
|
# there was resolved instead, and an old one failed the compiler check.
|
||||||
|
@{ Name = 'the compiler is resolved from Visual Studio, not PATH'; Args = @('-s', '-l', '-x')
|
||||||
|
Env = @{ PATH = $clangOnPath }
|
||||||
|
Match = @('^Compiler: .*/VC/Tools/Llvm/[^/]+/bin/clang-cl\.exe$') }
|
||||||
|
@{ Name = 'msvc names no compiler, having resolved none'; Args = @('-s')
|
||||||
|
NotContains = @('Compiler: ') }
|
||||||
|
@{ Name = '-l without -x names none either, the toolset picks it'; Args = @('-s', '-l')
|
||||||
|
NotContains = @('Compiler: ') }
|
||||||
|
# An empty ProgramFiles(x86) puts vswhere out of reach, which is a machine
|
||||||
|
# whose Visual Studio has no clang toolset.
|
||||||
|
@{ Name = 'without a Visual Studio clang the one on PATH is used and named'; Args = @('-s', '-l', '-x')
|
||||||
|
Env = @{ 'ProgramFiles(x86)' = $noVs; PATH = $clangOnPath }
|
||||||
|
Contains = @('Visual Studio has no clang-cl')
|
||||||
|
Match = @('^Compiler: .*/clang/clang-cl\.exe$') }
|
||||||
|
@{ Name = 'no clang-cl anywhere stops before configuring'; Args = @('-s', '-l', '-x'); ExpectExit = 1
|
||||||
|
Env = @{ 'ProgramFiles(x86)' = $noVs; PATH = 'C:\Windows\system32;C:\Windows' }
|
||||||
|
Contains = @('No clang-cl found', '--install-vs ide -l')
|
||||||
|
NotContains = @('cmake -B') }
|
||||||
|
# Only a configure passes the compiler to CMake, so an action that does
|
||||||
|
# not configure resolves none, and cannot start needing one installed.
|
||||||
|
@{ Name = 'packing resolves no compiler'; Args = @('-p', '-l', '-x')
|
||||||
|
Contains = @('Packing the dependencies')
|
||||||
|
NotContains = @('Compiler: ') }
|
||||||
|
@{ Name = '--no-configure resolves none either'; Args = @('-s', '-l', '-x', '--no-configure')
|
||||||
|
Contains = @('cmake --build "build-clang"')
|
||||||
|
NotContains = @('Compiler: ') }
|
||||||
@{ Name = '-l alone uses the ClangCL toolset on the VS generator'; Args = @('-d', '-l')
|
@{ Name = '-l alone uses the ClangCL toolset on the VS generator'; Args = @('-d', '-l')
|
||||||
Contains = @('-G "Visual Studio', '-T ClangCL')
|
Contains = @('-G "Visual Studio', '-T ClangCL')
|
||||||
NotContains = @('-DCMAKE_C_COMPILER') }
|
NotContains = @('-DCMAKE_C_COMPILER') }
|
||||||
@@ -148,11 +195,13 @@ $cases = @(
|
|||||||
NotContains = @('clang-cl') }
|
NotContains = @('clang-cl') }
|
||||||
@{ Name = '--msbuild with -l gives the VS generator and the ClangCL toolset'; Args = @('-d', '--msbuild', '-l')
|
@{ Name = '--msbuild with -l gives the VS generator and the ClangCL toolset'; Args = @('-d', '--msbuild', '-l')
|
||||||
Contains = @('-G "Visual Studio', '-T ClangCL') }
|
Contains = @('-G "Visual Studio', '-T ClangCL') }
|
||||||
# A developer with a standalone LLVM points at it; the VS-bundled clang
|
# A developer with a standalone LLVM points at it, and the path is passed
|
||||||
# is what a bare clang-cl.exe resolves to after the dev shell runs.
|
# with forward slashes so CMake cannot read a backslash as an escape.
|
||||||
@{ Name = '--clang-path names the compiler, quoted for its spaces'; Args = @('-d', '-x', '--clang-path', 'C:\Program Files\LLVM\bin\clang-cl.exe')
|
@{ Name = '--clang-path names the compiler, quoted for its spaces'; Args = @('-d', '-x', '--clang-path', 'C:\Program Files\LLVM\bin\clang-cl.exe')
|
||||||
Contains = @('-DCMAKE_C_COMPILER="C:\Program Files\LLVM\bin\clang-cl.exe"',
|
Contains = @('-DCMAKE_C_COMPILER="C:/Program Files/LLVM/bin/clang-cl.exe"',
|
||||||
'-DCMAKE_CXX_COMPILER="C:\Program Files\LLVM\bin\clang-cl.exe"') }
|
'-DCMAKE_CXX_COMPILER="C:/Program Files/LLVM/bin/clang-cl.exe"') }
|
||||||
|
@{ Name = '--clang-path beats the Visual Studio clang'; Args = @('-s', '-x', '--clang-path', 'C:\Program Files\LLVM\bin\clang-cl.exe')
|
||||||
|
Contains = @('Compiler: C:/Program Files/LLVM/bin/clang-cl.exe') }
|
||||||
@{ Name = '--clang-path is a clang request on its own'; Args = @('-d', '-x', '--clang-path', 'C:\Program Files\LLVM\bin\clang-cl.exe')
|
@{ Name = '--clang-path is a clang request on its own'; Args = @('-d', '-x', '--clang-path', 'C:\Program Files\LLVM\bin\clang-cl.exe')
|
||||||
Contains = @('deps/build-clang') }
|
Contains = @('deps/build-clang') }
|
||||||
@{ Name = '--clang-path needs Ninja to take effect'; Args = @('-d', '--clang-path', 'C:\Program Files\LLVM\bin\clang-cl.exe'); ExpectExit = 1
|
@{ Name = '--clang-path needs Ninja to take effect'; Args = @('-d', '--clang-path', 'C:\Program Files\LLVM\bin\clang-cl.exe'); ExpectExit = 1
|
||||||
@@ -195,7 +244,8 @@ $cases = @(
|
|||||||
@{ Name = 'the architecture is matched case-insensitively'; Args = @('-d', '--arch', 'ARM64')
|
@{ Name = 'the architecture is matched case-insensitively'; Args = @('-d', '--arch', 'ARM64')
|
||||||
Contains = @('-A ARM64', 'deps/build-arm64') }
|
Contains = @('-A ARM64', 'deps/build-arm64') }
|
||||||
@{ Name = 'arm64 under Ninja has no -A but keeps the arm64 tree'; Args = @('-d', '--arch', 'arm64', '-x', '-l')
|
@{ Name = 'arm64 under Ninja has no -A but keeps the arm64 tree'; Args = @('-d', '--arch', 'arm64', '-x', '-l')
|
||||||
Contains = @('deps/build-clang-arm64', '-DCMAKE_C_COMPILER=clang-cl.exe')
|
Contains = @('deps/build-clang-arm64')
|
||||||
|
Match = @('-DCMAKE_C_COMPILER="[^"]+/clang-cl\.exe"')
|
||||||
NotContains = @('-A ') }
|
NotContains = @('-A ') }
|
||||||
|
|
||||||
'build configurations'
|
'build configurations'
|
||||||
@@ -699,18 +749,28 @@ $cases = @(
|
|||||||
Contains = @('Next', 'Rebuild after edits') }
|
Contains = @('Next', 'Rebuild after edits') }
|
||||||
|
|
||||||
'pointing at the solution'
|
'pointing at the solution'
|
||||||
|
# The extension follows the generator, so these two pin the release and a
|
||||||
|
# build directory that cannot already hold a solution of either kind.
|
||||||
|
@{ Name = 'the 2026 generator gets the XML solution'; Args = @('-s', '--vs', '2026', '--build-dir', 'D:\tree')
|
||||||
|
Contains = @('Solution D:\tree\OrcaSlicer.slnx', 'Open in Visual Studio D:\tree\OrcaSlicer.slnx') }
|
||||||
|
@{ Name = 'the releases before it get the classic one'; Args = @('-s', '--vs', '2022', '--build-dir', 'D:\tree')
|
||||||
|
Contains = @('Solution D:\tree\OrcaSlicer.sln', 'Open in Visual Studio D:\tree\OrcaSlicer.sln') }
|
||||||
|
@{ Name = 'a solution already on disk wins over the generator'; Args = @('-s', '--vs', '2026', '--build-dir', $slnDir)
|
||||||
|
Match = @('^ Solution .*\\OrcaSlicer\.sln$') }
|
||||||
|
# Extension-agnostic from here: these cases are about the directory, and
|
||||||
|
# the release is whatever is installed.
|
||||||
@{ Name = 'the VS generator says where the solution is'; Args = @('-s')
|
@{ Name = 'the VS generator says where the solution is'; Args = @('-s')
|
||||||
Match = @('^ Solution .*\\build\\OrcaSlicer\.sln$') }
|
Match = @('^ Solution .*\\build\\OrcaSlicer\.slnx?$') }
|
||||||
@{ Name = 'the solution path follows the configuration'; Args = @('-s', '--config', 'debug')
|
@{ Name = 'the solution path follows the configuration'; Args = @('-s', '--config', 'debug')
|
||||||
Match = @('^ Solution .*\\build-dbg\\OrcaSlicer\.sln$') }
|
Match = @('^ Solution .*\\build-dbg\\OrcaSlicer\.slnx?$') }
|
||||||
@{ Name = 'the solution line survives an install'; Args = @('-s', '-i')
|
@{ Name = 'the solution line survives an install'; Args = @('-s', '-i')
|
||||||
Contains = @(' Solution ') }
|
Contains = @(' Solution ') }
|
||||||
# The path is resolved, not pasted onto the repository root, so it is
|
# The path is resolved, not pasted onto the repository root, so it is
|
||||||
# right whether --build-dir came absolute or with forward slashes.
|
# right whether --build-dir came absolute or with forward slashes.
|
||||||
@{ Name = 'a moved build still prints one real path'; Args = @('-s', '--build-dir', 'out/build/x64-clang')
|
@{ Name = 'a moved build still prints one real path'; Args = @('-s', '--build-dir', 'out/build/x64-clang')
|
||||||
Match = @('^ Solution [A-Za-z]:\\[^/]+\\OrcaSlicer\.sln$') }
|
Match = @('^ Solution [A-Za-z]:\\[^/]+\\OrcaSlicer\.slnx?$') }
|
||||||
@{ Name = 'an absolute --build-dir is not glued onto the repo root'; Args = @('-s', '--build-dir', 'D:\tree')
|
@{ Name = 'an absolute --build-dir is not glued onto the repo root'; Args = @('-s', '--build-dir', 'D:\tree')
|
||||||
Contains = @('Solution D:\tree\OrcaSlicer.sln') }
|
Match = @('^ Solution D:\\tree\\OrcaSlicer\.slnx?$') }
|
||||||
)
|
)
|
||||||
|
|
||||||
function Invoke-BuildScript {
|
function Invoke-BuildScript {
|
||||||
|
|||||||
+1
-1
@@ -7384,7 +7384,7 @@ void CLI::print_help(bool include_print_options, PrinterTechnology printer_techn
|
|||||||
<< std::endl
|
<< std::endl
|
||||||
<< "Print setting priorities:" << std::endl
|
<< "Print setting priorities:" << std::endl
|
||||||
<< "\t1) setting values from the command line (highest priority)"<< std::endl
|
<< "\t1) setting values from the command line (highest priority)"<< std::endl
|
||||||
<< "\t2) setting values loaded with --load_settings and --load_filaments" << std::endl
|
<< "\t2) setting values loaded with --load-settings and --load-filaments" << std::endl
|
||||||
<< "\t3) setting values loaded from 3mf(lowest priority)" << std::endl;
|
<< "\t3) setting values loaded from 3mf(lowest priority)" << std::endl;
|
||||||
|
|
||||||
/*if (include_print_options) {
|
/*if (include_print_options) {
|
||||||
|
|||||||
@@ -1715,6 +1715,36 @@ const ConfigOption* DynamicConfig::optptr(const t_config_option_key &opt_key) co
|
|||||||
return (it == options.end()) ? nullptr : it->second.get();
|
return (it == options.end()) ? nullptr : it->second.get();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ConfigOptionBool(s)::deserialize only understands "1" and "0", but scripts commonly spell CLI
|
||||||
|
// flags as --opt=true or --opt=no. Map the usual spellings onto what deserialize() accepts, per
|
||||||
|
// comma-separated item so vector options keep working, and pass anything else through unchanged
|
||||||
|
// so a genuine typo is still reported as invalid.
|
||||||
|
static std::string normalize_cli_bool_value(const std::string &value)
|
||||||
|
{
|
||||||
|
static const char* true_values[] = { "1", "true", "yes", "on", "enabled" };
|
||||||
|
static const char* false_values[] = { "0", "false", "no", "off", "disabled" };
|
||||||
|
|
||||||
|
auto matches = [](const std::string &item, const char* const* candidates, size_t count) {
|
||||||
|
return std::any_of(candidates, candidates + count, [&item](const char* candidate) { return boost::iequals(item, candidate); });
|
||||||
|
};
|
||||||
|
|
||||||
|
std::string normalized;
|
||||||
|
std::istringstream is(value);
|
||||||
|
std::string item;
|
||||||
|
while (std::getline(is, item, ',')) {
|
||||||
|
boost::trim(item);
|
||||||
|
if (! normalized.empty())
|
||||||
|
normalized += ",";
|
||||||
|
if (matches(item, true_values, std::size(true_values)))
|
||||||
|
normalized += "1";
|
||||||
|
else if (matches(item, false_values, std::size(false_values)))
|
||||||
|
normalized += "0";
|
||||||
|
else
|
||||||
|
normalized += item;
|
||||||
|
}
|
||||||
|
return normalized;
|
||||||
|
}
|
||||||
|
|
||||||
bool DynamicConfig::read_cli(int argc, const char* const argv[], t_config_option_keys* extra, t_config_option_keys* keys)
|
bool DynamicConfig::read_cli(int argc, const char* const argv[], t_config_option_keys* extra, t_config_option_keys* keys)
|
||||||
{
|
{
|
||||||
// cache the CLI option => opt_key mapping
|
// cache the CLI option => opt_key mapping
|
||||||
@@ -1812,17 +1842,32 @@ bool DynamicConfig::read_cli(int argc, const char* const argv[], t_config_option
|
|||||||
// to the end of the value.
|
// to the end of the value.
|
||||||
if (opt_base->type() == coBools && value.empty())
|
if (opt_base->type() == coBools && value.empty())
|
||||||
static_cast<ConfigOptionBools*>(opt_base)->values.push_back(!no);
|
static_cast<ConfigOptionBools*>(opt_base)->values.push_back(!no);
|
||||||
else
|
else {
|
||||||
// Deserialize any other vector value (ConfigOptionInts, Floats, Percents, Points) the same way
|
// Deserialize any other vector value (ConfigOptionInts, Floats, Percents, Points) the same way
|
||||||
// they get deserialized from an .ini file. For ConfigOptionStrings, that means that the C-style unescape
|
// they get deserialized from an .ini file. For ConfigOptionStrings, that means that the C-style unescape
|
||||||
// will be applied for values enclosed in quotes, while values non-enclosed in quotes are left to be
|
// will be applied for values enclosed in quotes, while values non-enclosed in quotes are left to be
|
||||||
// unescaped by the calling shell.
|
// unescaped by the calling shell.
|
||||||
opt_vector->deserialize(value, true);
|
const std::string vector_value = opt_base->type() == coBools ? normalize_cli_bool_value(value) : value;
|
||||||
|
bool deserialized = false;
|
||||||
|
try {
|
||||||
|
deserialized = opt_vector->deserialize(vector_value, true);
|
||||||
|
} catch (const std::exception &ex) {
|
||||||
|
// e.g. "nil" deserialized into a non-nullable vector option throws instead of
|
||||||
|
// returning false - treat that the same as any other invalid value here.
|
||||||
|
deserialized = false;
|
||||||
|
}
|
||||||
|
if (! deserialized) {
|
||||||
|
boost::nowide::cerr << "Invalid value for option --" << token.c_str() << std::endl;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
} else if (opt_base->type() == coBool) {
|
} else if (opt_base->type() == coBool) {
|
||||||
if (value.empty())
|
if (value.empty())
|
||||||
static_cast<ConfigOptionBool*>(opt_base)->value = !no;
|
static_cast<ConfigOptionBool*>(opt_base)->value = !no;
|
||||||
else
|
else if (! opt_base->deserialize(normalize_cli_bool_value(value))) {
|
||||||
opt_base->deserialize(value);
|
boost::nowide::cerr << "Invalid value for option --" << token.c_str() << std::endl;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
} else if (opt_base->type() == coString) {
|
} else if (opt_base->type() == coString) {
|
||||||
// Do not unescape single string values, the unescaping is left to the calling shell.
|
// Do not unescape single string values, the unescaping is left to the calling shell.
|
||||||
static_cast<ConfigOptionString*>(opt_base)->value = value;
|
static_cast<ConfigOptionString*>(opt_base)->value = value;
|
||||||
|
|||||||
@@ -33,15 +33,6 @@ public:
|
|||||||
SurfaceFeature(const Vec3d& pt)
|
SurfaceFeature(const Vec3d& pt)
|
||||||
: m_type{SurfaceFeatureType::Point}, m_pt1{pt} {}
|
: m_type{SurfaceFeatureType::Point}, m_pt1{pt} {}
|
||||||
|
|
||||||
SurfaceFeature(const SurfaceFeature& sf){
|
|
||||||
this->clone(sf);
|
|
||||||
volume = sf.volume;
|
|
||||||
plane_indices = sf.plane_indices;
|
|
||||||
world_tran = sf.world_tran;
|
|
||||||
world_plane_features = sf.world_plane_features;
|
|
||||||
origin_surface_feature = sf.origin_surface_feature;
|
|
||||||
}
|
|
||||||
|
|
||||||
void clone(const SurfaceFeature &sf)
|
void clone(const SurfaceFeature &sf)
|
||||||
{
|
{
|
||||||
m_type = sf.get_type();
|
m_type = sf.get_type();
|
||||||
|
|||||||
@@ -39,7 +39,6 @@ namespace orientation {
|
|||||||
float height_to_bottom_hull_ratio = 0; // affects stability, the lower the better
|
float height_to_bottom_hull_ratio = 0; // affects stability, the lower the better
|
||||||
float unprintability = 0;
|
float unprintability = 0;
|
||||||
Eigen::VectorXf areas_cooling;
|
Eigen::VectorXf areas_cooling;
|
||||||
CostItems(CostItems const & other) = default;
|
|
||||||
CostItems() = default;
|
CostItems() = default;
|
||||||
static std::string field_names() {
|
static std::string field_names() {
|
||||||
return " overhang, bottom, bothull, contour, A_laf, A_prj, unprintability";
|
return " overhang, bottom, bothull, contour, A_laf, A_prj, unprintability";
|
||||||
|
|||||||
@@ -195,7 +195,6 @@ public:
|
|||||||
Point(int64_t x, int32_t y) : Vec2crd(coord_t(x), coord_t(y)) {}
|
Point(int64_t x, int32_t y) : Vec2crd(coord_t(x), coord_t(y)) {}
|
||||||
Point(int32_t x, int64_t y) : Vec2crd(coord_t(x), coord_t(y)) {}
|
Point(int32_t x, int64_t y) : Vec2crd(coord_t(x), coord_t(y)) {}
|
||||||
Point(double x, double y) : Vec2crd(coord_t(std::round(x)), coord_t(std::round(y))) {}
|
Point(double x, double y) : Vec2crd(coord_t(std::round(x)), coord_t(std::round(y))) {}
|
||||||
Point(const Point &rhs) { *this = rhs; }
|
|
||||||
explicit Point(const Vec2d& rhs) : Vec2crd(coord_t(std::round(rhs.x())), coord_t(std::round(rhs.y()))) {}
|
explicit Point(const Vec2d& rhs) : Vec2crd(coord_t(std::round(rhs.x())), coord_t(std::round(rhs.y()))) {}
|
||||||
// This constructor allows you to construct Point from Eigen expressions
|
// This constructor allows you to construct Point from Eigen expressions
|
||||||
// This constructor has to be implicit (non-explicit) to allow implicit conversion from Eigen expressions.
|
// This constructor has to be implicit (non-explicit) to allow implicit conversion from Eigen expressions.
|
||||||
@@ -278,7 +277,6 @@ public:
|
|||||||
Point3(int32_t x, int32_t y, int32_t z = 0) : Vec3crd(coord_t(x), coord_t(y), coord_t(z)) {}
|
Point3(int32_t x, int32_t y, int32_t z = 0) : Vec3crd(coord_t(x), coord_t(y), coord_t(z)) {}
|
||||||
Point3(int64_t x, int64_t y, int64_t z = 0) : Vec3crd(coord_t(x), coord_t(y), coord_t(z)) {}
|
Point3(int64_t x, int64_t y, int64_t z = 0) : Vec3crd(coord_t(x), coord_t(y), coord_t(z)) {}
|
||||||
Point3(double x, double y, double z = 0.0) : Vec3crd(coord_t(std::round(x)), coord_t(std::round(y)), coord_t(std::round(z))) {}
|
Point3(double x, double y, double z = 0.0) : Vec3crd(coord_t(std::round(x)), coord_t(std::round(y)), coord_t(std::round(z))) {}
|
||||||
Point3(const Point3 &rhs) { *this = rhs; }
|
|
||||||
explicit Point3(const Vec2crd& vec2crd, coord_t z = 0) : Vec3crd(vec2crd.x(), vec2crd.y(), z) {}
|
explicit Point3(const Vec2crd& vec2crd, coord_t z = 0) : Vec3crd(vec2crd.x(), vec2crd.y(), z) {}
|
||||||
explicit Point3(const Vec3crd &vec3crd) : Vec3crd(vec3crd) {}
|
explicit Point3(const Vec3crd &vec3crd) : Vec3crd(vec3crd) {}
|
||||||
// This constructor allows you to construct Point from Eigen expressions
|
// This constructor allows you to construct Point from Eigen expressions
|
||||||
|
|||||||
@@ -983,15 +983,19 @@ BedType Preset::get_default_bed_type(PresetBundle* preset_bundle)
|
|||||||
if (config.has("default_bed_type") && !config.opt_string("default_bed_type").empty()) {
|
if (config.has("default_bed_type") && !config.opt_string("default_bed_type").empty()) {
|
||||||
try {
|
try {
|
||||||
std::string str_bed_type = config.opt_string("default_bed_type");
|
std::string str_bed_type = config.opt_string("default_bed_type");
|
||||||
|
BedType bed_type;
|
||||||
|
if (ConfigOptionEnum<BedType>::from_string(str_bed_type, bed_type) &&
|
||||||
|
bed_type > btDefault && bed_type < btCount) {
|
||||||
|
return bed_type;
|
||||||
|
}
|
||||||
|
|
||||||
// Try parsing as integer first (legacy format)
|
// Try parsing as integer (legacy format)
|
||||||
int bed_type_value = atoi(str_bed_type.c_str());
|
int bed_type_value = atoi(str_bed_type.c_str());
|
||||||
if (bed_type_value > 0) {
|
if (bed_type_value > 0 && bed_type_value < BedType::btCount) {
|
||||||
return BedType(bed_type_value);
|
return BedType(bed_type_value);
|
||||||
}
|
}
|
||||||
else {
|
|
||||||
BOOST_LOG_TRIVIAL(error) << "default_bed_type: invalid bed type: " << str_bed_type;
|
BOOST_LOG_TRIVIAL(error) << "default_bed_type: invalid bed type: " << str_bed_type;
|
||||||
}
|
|
||||||
return BedType::btPEI;
|
return BedType::btPEI;
|
||||||
|
|
||||||
} catch(...) {
|
} catch(...) {
|
||||||
|
|||||||
@@ -856,13 +856,12 @@ public:
|
|||||||
|
|
||||||
protected:
|
protected:
|
||||||
PresetCollection() = default;
|
PresetCollection() = default;
|
||||||
// Copy constructor and copy operators are not to be used from outside PresetBundle,
|
// Deleted by the std::recursive_mutex member. PresetBundle copies by assignment.
|
||||||
// as the Profile::vendor points to an instance of VendorProfile stored at parent PresetBundle!
|
PresetCollection(const PresetCollection &other) = delete;
|
||||||
PresetCollection(const PresetCollection &other) = default;
|
//BBS: hand-written because m_mutex cannot be copy-assigned.
|
||||||
//BBS: add operator= logic insteadof default
|
|
||||||
PresetCollection& operator=(const PresetCollection &other);
|
PresetCollection& operator=(const PresetCollection &other);
|
||||||
// After copying a collection with the default operators above, call this function
|
// Copying leaves every Preset::vendor pointing into the source bundle's vendor map.
|
||||||
// to adjust Profile::vendor pointers.
|
// This re-points them at the matching entries in vendors.
|
||||||
void update_vendor_ptrs_after_copy(const VendorMap &vendors);
|
void update_vendor_ptrs_after_copy(const VendorMap &vendors);
|
||||||
|
|
||||||
// Select a preset, if it exists. If it does not exist, select an invalid (-1) index.
|
// Select a preset, if it exists. If it does not exist, select an invalid (-1) index.
|
||||||
@@ -1000,7 +999,8 @@ public:
|
|||||||
bool only_default_printers() const;
|
bool only_default_printers() const;
|
||||||
private:
|
private:
|
||||||
PrinterPresetCollection() = default;
|
PrinterPresetCollection() = default;
|
||||||
PrinterPresetCollection(const PrinterPresetCollection &other) = default;
|
// Deleted along with the base copy constructor.
|
||||||
|
PrinterPresetCollection(const PrinterPresetCollection &other) = delete;
|
||||||
PrinterPresetCollection& operator=(const PrinterPresetCollection &other) = default;
|
PrinterPresetCollection& operator=(const PrinterPresetCollection &other) = default;
|
||||||
|
|
||||||
friend class PresetBundle;
|
friend class PresetBundle;
|
||||||
|
|||||||
@@ -2941,6 +2941,16 @@ void PresetBundle::load_selections(AppConfig &config, const PresetPreferences& p
|
|||||||
// If executed due to a Config Wizard update, preferred_printer contains the first newly installed printer, otherwise nullptr.
|
// If executed due to a Config Wizard update, preferred_printer contains the first newly installed printer, otherwise nullptr.
|
||||||
const Preset *preferred_printer = printers.find_system_preset_by_model_and_variant(preferred_selection.printer_model_id, preferred_selection.printer_variant);
|
const Preset *preferred_printer = printers.find_system_preset_by_model_and_variant(preferred_selection.printer_model_id, preferred_selection.printer_variant);
|
||||||
printers.select_preset_by_name(preferred_printer ? preferred_printer->name : initial_printer_profile_name, true);
|
printers.select_preset_by_name(preferred_printer ? preferred_printer->name : initial_printer_profile_name, true);
|
||||||
|
Preset &selected_printer = printers.get_edited_preset();
|
||||||
|
if (selected_printer.printer_technology() == ptFFF) {
|
||||||
|
BedType bed_type = selected_printer.get_default_bed_type(this);
|
||||||
|
const std::string saved_bed_type = config.get_printer_setting(selected_printer.name, "curr_bed_type");
|
||||||
|
const int saved_bed_type_value = atoi(saved_bed_type.c_str());
|
||||||
|
if (saved_bed_type_value > btDefault && saved_bed_type_value < btCount)
|
||||||
|
bed_type = static_cast<BedType>(saved_bed_type_value);
|
||||||
|
project_config.set_key_value("curr_bed_type", new ConfigOptionEnum<BedType>(bed_type));
|
||||||
|
config.set("curr_bed_type", std::to_string(static_cast<int>(bed_type)));
|
||||||
|
}
|
||||||
CNumericLocalesSetter locales_setter;
|
CNumericLocalesSetter locales_setter;
|
||||||
|
|
||||||
// Orca: load from orca_presets
|
// Orca: load from orca_presets
|
||||||
|
|||||||
@@ -11990,13 +11990,11 @@ CLIActionsConfigDef::CLIActionsConfigDef()
|
|||||||
def = this->add("load_defaultfila", coBool);
|
def = this->add("load_defaultfila", coBool);
|
||||||
def->label = L("Load default filaments");
|
def->label = L("Load default filaments");
|
||||||
def->tooltip = L("Load first filament as default for those not loaded.");
|
def->tooltip = L("Load first filament as default for those not loaded.");
|
||||||
def->cli_params = "option";
|
|
||||||
def->set_default_value(new ConfigOptionBool(false));
|
def->set_default_value(new ConfigOptionBool(false));
|
||||||
|
|
||||||
def = this->add("min_save", coBool);
|
def = this->add("min_save", coBool);
|
||||||
def->label = L("Minimum save");
|
def->label = L("Minimum save");
|
||||||
def->tooltip = L("Export 3MF with minimum size.");
|
def->tooltip = L("Export 3MF with minimum size.");
|
||||||
def->cli_params = "option";
|
|
||||||
def->set_default_value(new ConfigOptionBool(false));
|
def->set_default_value(new ConfigOptionBool(false));
|
||||||
|
|
||||||
def = this->add("mtcpp", coInt);
|
def = this->add("mtcpp", coInt);
|
||||||
@@ -12022,7 +12020,6 @@ CLIActionsConfigDef::CLIActionsConfigDef()
|
|||||||
def = this->add("normative_check", coBool);
|
def = this->add("normative_check", coBool);
|
||||||
def->label = L("Normative check");
|
def->label = L("Normative check");
|
||||||
def->tooltip = L("Check the normative items.");
|
def->tooltip = L("Check the normative items.");
|
||||||
def->cli_params = "option";
|
|
||||||
def->set_default_value(new ConfigOptionBool(true));
|
def->set_default_value(new ConfigOptionBool(true));
|
||||||
|
|
||||||
/*def = this->add("help_fff", coBool);
|
/*def = this->add("help_fff", coBool);
|
||||||
@@ -12289,7 +12286,7 @@ CLIMiscConfigDef::CLIMiscConfigDef()
|
|||||||
def->cli_params = "level";
|
def->cli_params = "level";
|
||||||
def->set_default_value(new ConfigOptionInt(1));
|
def->set_default_value(new ConfigOptionInt(1));
|
||||||
|
|
||||||
def = this->add("logfile", coInt);
|
def = this->add("logfile", coString);
|
||||||
def->label = L("Log file");
|
def->label = L("Log file");
|
||||||
def->tooltip = L("Redirects debug logging to file.\n");
|
def->tooltip = L("Redirects debug logging to file.\n");
|
||||||
def->cli_params = "file";
|
def->cli_params = "file";
|
||||||
@@ -12337,7 +12334,6 @@ CLIMiscConfigDef::CLIMiscConfigDef()
|
|||||||
def = this->add("skip_modified_gcodes", coBool);
|
def = this->add("skip_modified_gcodes", coBool);
|
||||||
def->label = L("Skip modified G-code in 3MF");
|
def->label = L("Skip modified G-code in 3MF");
|
||||||
def->tooltip = L("Skip the modified G-code in 3MF from printer or filament presets.");
|
def->tooltip = L("Skip the modified G-code in 3MF from printer or filament presets.");
|
||||||
def->cli_params = "option";
|
|
||||||
def->set_default_value(new ConfigOptionBool(false));
|
def->set_default_value(new ConfigOptionBool(false));
|
||||||
|
|
||||||
def = this->add("makerlab_name", coString);
|
def = this->add("makerlab_name", coString);
|
||||||
@@ -12367,14 +12363,12 @@ CLIMiscConfigDef::CLIMiscConfigDef()
|
|||||||
def = this->add("allow_newer_file", coBool);
|
def = this->add("allow_newer_file", coBool);
|
||||||
def->label = L("Allow 3MF with newer version to be sliced");
|
def->label = L("Allow 3MF with newer version to be sliced");
|
||||||
def->tooltip = L("Allow 3MF with newer version to be sliced.");
|
def->tooltip = L("Allow 3MF with newer version to be sliced.");
|
||||||
def->cli_params = "option";
|
|
||||||
def->set_default_value(new ConfigOptionBool(false));
|
def->set_default_value(new ConfigOptionBool(false));
|
||||||
|
|
||||||
def = this->add("allow_mix_temp", coBool);
|
def = this->add("allow_mix_temp", coBool);
|
||||||
// internal use only, don't need translation
|
// internal use only, don't need translation
|
||||||
def->label = "Allow filaments with high/low temperature to be printed together";
|
def->label = "Allow filaments with high/low temperature to be printed together";
|
||||||
def->tooltip = "Allow filaments with high/low temperature to be printed together.";
|
def->tooltip = "Allow filaments with high/low temperature to be printed together.";
|
||||||
def->cli_params = "option";
|
|
||||||
def->set_default_value(new ConfigOptionBool(false));
|
def->set_default_value(new ConfigOptionBool(false));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -44,9 +44,6 @@ struct DrainHole
|
|||||||
: pos(p), normal(n), radius(r), height(h), failed(fl)
|
: pos(p), normal(n), radius(r), height(h), failed(fl)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
DrainHole(const DrainHole& rhs) :
|
|
||||||
DrainHole(rhs.pos, rhs.normal, rhs.radius, rhs.height, rhs.failed) {}
|
|
||||||
|
|
||||||
bool operator==(const DrainHole &sp) const;
|
bool operator==(const DrainHole &sp) const;
|
||||||
|
|
||||||
bool operator!=(const DrainHole &sp) const { return !(sp == (*this)); }
|
bool operator!=(const DrainHole &sp) const { return !(sp == (*this)); }
|
||||||
|
|||||||
@@ -1234,10 +1234,6 @@ static void modulate_extrusion_by_overlapping_layers(
|
|||||||
(fragment_end.is_start ? &polyline.points.front() : &polyline.points.back());
|
(fragment_end.is_start ? &polyline.points.front() : &polyline.points.back());
|
||||||
}
|
}
|
||||||
private:
|
private:
|
||||||
ExtrusionPathFragmentEndPointAccessor& operator=(const ExtrusionPathFragmentEndPointAccessor&) {
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
const std::vector<ExtrusionPathFragment> &m_path_fragments;
|
const std::vector<ExtrusionPathFragment> &m_path_fragments;
|
||||||
};
|
};
|
||||||
const coord_t search_radius = 7;
|
const coord_t search_radius = 7;
|
||||||
|
|||||||
@@ -204,8 +204,9 @@ public:
|
|||||||
clear_nodes();
|
clear_nodes();
|
||||||
}
|
}
|
||||||
|
|
||||||
TreeSupportData(TreeSupportData&&) = default;
|
// Deleted by the tbb::spin_mutex member.
|
||||||
TreeSupportData& operator=(TreeSupportData&&) = default;
|
TreeSupportData(TreeSupportData&&) = delete;
|
||||||
|
TreeSupportData& operator=(TreeSupportData&&) = delete;
|
||||||
|
|
||||||
TreeSupportData(const TreeSupportData&) = delete;
|
TreeSupportData(const TreeSupportData&) = delete;
|
||||||
TreeSupportData& operator=(const TreeSupportData&) = delete;
|
TreeSupportData& operator=(const TreeSupportData&) = delete;
|
||||||
|
|||||||
+3
-17
@@ -91,29 +91,15 @@ class CaliPresetInfo
|
|||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
int tray_id;
|
int tray_id;
|
||||||
int extruder_id;
|
int extruder_id = 0;
|
||||||
NozzleVolumeType nozzle_volume_type;
|
NozzleVolumeType nozzle_volume_type{nvtStandard};
|
||||||
BedType bed_type;
|
BedType bed_type{btDefault};
|
||||||
float nozzle_diameter;
|
float nozzle_diameter;
|
||||||
int nozzle_pos_id{-1};
|
int nozzle_pos_id{-1};
|
||||||
std::string nozzle_sn;
|
std::string nozzle_sn;
|
||||||
std::string filament_id;
|
std::string filament_id;
|
||||||
std::string setting_id;
|
std::string setting_id;
|
||||||
std::string name;
|
std::string name;
|
||||||
|
|
||||||
CaliPresetInfo &operator=(const CaliPresetInfo &other)
|
|
||||||
{
|
|
||||||
this->tray_id = other.tray_id;
|
|
||||||
this->extruder_id = other.extruder_id;
|
|
||||||
this->nozzle_volume_type = other.nozzle_volume_type;
|
|
||||||
this->nozzle_diameter = other.nozzle_diameter;
|
|
||||||
this->nozzle_pos_id = other.nozzle_pos_id;
|
|
||||||
this->nozzle_sn = other.nozzle_sn;
|
|
||||||
this->filament_id = other.filament_id;
|
|
||||||
this->setting_id = other.setting_id;
|
|
||||||
this->name = other.name;
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
struct PrinterCaliInfo
|
struct PrinterCaliInfo
|
||||||
|
|||||||
@@ -675,16 +675,6 @@ public:
|
|||||||
offset = Vec2d(0, 0);
|
offset = Vec2d(0, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
TexturePart(const TexturePart& part) {
|
|
||||||
this->x = part.x;
|
|
||||||
this->y = part.y;
|
|
||||||
this->w = part.w;
|
|
||||||
this->h = part.h;
|
|
||||||
this->offset = part.offset;
|
|
||||||
this->buffer = part.buffer;
|
|
||||||
this->filename = part.filename;
|
|
||||||
this->texture = part.texture;
|
|
||||||
}
|
|
||||||
void update_pos(float xx, float yy, float ww, float hh) {
|
void update_pos(float xx, float yy, float ww, float hh) {
|
||||||
x = xx;
|
x = xx;
|
||||||
y = yy;
|
y = yy;
|
||||||
|
|||||||
@@ -149,7 +149,10 @@ SavePresetDialog::Item::Item(Preset::Type type, const std::string &suffix, wxBox
|
|||||||
// Set initial state (unchecked by default)
|
// Set initial state (unchecked by default)
|
||||||
detach_checkbox->SetValue(m_detach);
|
detach_checkbox->SetValue(m_detach);
|
||||||
// Bind the checkbox event to update the detach state for this item
|
// Bind the checkbox event to update the detach state for this item
|
||||||
detach_checkbox->Bind(wxEVT_TOGGLEBUTTON, [this, detach_checkbox](wxCommandEvent&) { m_detach = detach_checkbox->GetValue(); });
|
detach_checkbox->Bind(wxEVT_TOGGLEBUTTON, [this, detach_checkbox](wxCommandEvent& event) {
|
||||||
|
m_detach = detach_checkbox->GetValue();
|
||||||
|
event.Skip(); // Let CheckBox update its bitmap for the new state.
|
||||||
|
});
|
||||||
|
|
||||||
detach_label->SetForegroundColour(wxColour("#363636"));
|
detach_label->SetForegroundColour(wxColour("#363636"));
|
||||||
|
|
||||||
|
|||||||
@@ -5131,7 +5131,7 @@ void TabPrinter::build_fff()
|
|||||||
optgroup->append_single_option_line("adaptive_bed_mesh_margin", "printer_basic_information_adaptive_bed_mesh#mesh-margin");
|
optgroup->append_single_option_line("adaptive_bed_mesh_margin", "printer_basic_information_adaptive_bed_mesh#mesh-margin");
|
||||||
|
|
||||||
optgroup = page->new_optgroup(L("Accessory"), "param_accessory");
|
optgroup = page->new_optgroup(L("Accessory"), "param_accessory");
|
||||||
optgroup->append_single_option_line("nozzle_type", "printer_basic_information_accessory#nozzle-type");
|
optgroup->append_single_option_line("nozzle_type", "printer_basic_information_accessory#nozzle-type", 0);
|
||||||
optgroup->append_single_option_line("nozzle_hrc", "printer_basic_information_accessory#nozzle-hrc");
|
optgroup->append_single_option_line("nozzle_hrc", "printer_basic_information_accessory#nozzle-hrc");
|
||||||
optgroup->append_single_option_line("auxiliary_fan", "printer_basic_information_accessory#auxiliary-part-cooling-fan");
|
optgroup->append_single_option_line("auxiliary_fan", "printer_basic_information_accessory#auxiliary-part-cooling-fan");
|
||||||
optgroup->append_single_option_line("fan_direction");
|
optgroup->append_single_option_line("fan_direction");
|
||||||
|
|||||||
@@ -828,3 +828,226 @@ SCENARIO("ConfigOptionVector::set_to_index throws on incompatible type", "[Confi
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST_CASE("read_cli applies valid values and collects non-option arguments", "[Config]") {
|
||||||
|
Slic3r::DynamicPrintConfig config;
|
||||||
|
t_config_option_keys extra, keys;
|
||||||
|
const char* argv[] = {"orca-slicer", "--nozzle-temperature", "210,190", "--reduce-crossing-wall=1", "model.3mf"};
|
||||||
|
REQUIRE(config.read_cli(5, argv, &extra, &keys));
|
||||||
|
REQUIRE(config.opt<ConfigOptionInts>("nozzle_temperature")->values == std::vector<int>{210, 190});
|
||||||
|
REQUIRE(config.opt<ConfigOptionBool>("reduce_crossing_wall")->value);
|
||||||
|
REQUIRE(extra == t_config_option_keys{"model.3mf"});
|
||||||
|
REQUIRE(keys == t_config_option_keys{"nozzle_temperature", "reduce_crossing_wall"});
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_CASE("read_cli rejects nil for a non-nullable vector option", "[Config]") {
|
||||||
|
Slic3r::DynamicPrintConfig config;
|
||||||
|
t_config_option_keys extra, keys;
|
||||||
|
const char* argv[] = {"orca-slicer", "--nozzle-temperature", "nil"};
|
||||||
|
REQUIRE_FALSE(config.read_cli(3, argv, &extra, &keys));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_CASE("read_cli rejects an invalid boolean value", "[Config]") {
|
||||||
|
Slic3r::DynamicPrintConfig config;
|
||||||
|
t_config_option_keys extra, keys;
|
||||||
|
const char* argv[] = {"orca-slicer", "--reduce-crossing-wall=maybe"};
|
||||||
|
REQUIRE_FALSE(config.read_cli(2, argv, &extra, &keys));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_CASE("read_cli accepts the common spellings of a boolean value", "[Config]") {
|
||||||
|
const auto [text, expected] = GENERATE(table<const char*, bool>({
|
||||||
|
{"--reduce-crossing-wall=1", true },
|
||||||
|
{"--reduce-crossing-wall=true", true },
|
||||||
|
{"--reduce-crossing-wall=Yes", true },
|
||||||
|
{"--reduce-crossing-wall=on", true },
|
||||||
|
{"--reduce-crossing-wall=enabled", true },
|
||||||
|
{"--reduce-crossing-wall=TRUE", true },
|
||||||
|
{"--reduce-crossing-wall=oN", true },
|
||||||
|
{"--reduce-crossing-wall=0", false},
|
||||||
|
{"--reduce-crossing-wall=false", false},
|
||||||
|
{"--reduce-crossing-wall=No", false},
|
||||||
|
{"--reduce-crossing-wall=off", false},
|
||||||
|
{"--reduce-crossing-wall=disabled", false},
|
||||||
|
{"--reduce-crossing-wall=FALSE", false},
|
||||||
|
{"--reduce-crossing-wall=DiSaBlEd", false},
|
||||||
|
}));
|
||||||
|
|
||||||
|
DYNAMIC_SECTION(text) {
|
||||||
|
Slic3r::DynamicPrintConfig config;
|
||||||
|
t_config_option_keys extra, keys;
|
||||||
|
const char* argv[] = {"orca-slicer", text};
|
||||||
|
REQUIRE(config.read_cli(2, argv, &extra, &keys));
|
||||||
|
REQUIRE(config.opt<ConfigOptionBool>("reduce_crossing_wall")->value == expected);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_CASE("read_cli accepts the common boolean spellings inside a bools vector", "[Config]") {
|
||||||
|
Slic3r::DynamicPrintConfig config;
|
||||||
|
t_config_option_keys extra, keys;
|
||||||
|
const char* argv[] = {"orca-slicer", "--filament-soluble=true,no,1"};
|
||||||
|
REQUIRE(config.read_cli(2, argv, &extra, &keys));
|
||||||
|
REQUIRE(config.opt<ConfigOptionBools>("filament_soluble")->values == std::vector<unsigned char>{1, 0, 1});
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_CASE("read_cli trims whitespace around boolean spellings", "[Config]") {
|
||||||
|
Slic3r::DynamicPrintConfig config;
|
||||||
|
t_config_option_keys extra, keys;
|
||||||
|
const char* argv[] = {"orca-slicer", "--reduce-crossing-wall= true ", "--filament-soluble= true , no ,1"};
|
||||||
|
REQUIRE(config.read_cli(3, argv, &extra, &keys));
|
||||||
|
REQUIRE(config.opt<ConfigOptionBool>("reduce_crossing_wall")->value);
|
||||||
|
REQUIRE(config.opt<ConfigOptionBools>("filament_soluble")->values == std::vector<unsigned char>{1, 0, 1});
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_CASE("read_cli normalizes boolean spellings when a bools vector is repeated", "[Config]") {
|
||||||
|
Slic3r::DynamicPrintConfig config;
|
||||||
|
t_config_option_keys extra, keys;
|
||||||
|
const char* argv[] = {"orca-slicer", "--filament-soluble=true", "--filament-soluble=off"};
|
||||||
|
REQUIRE(config.read_cli(3, argv, &extra, &keys));
|
||||||
|
REQUIRE(config.opt<ConfigOptionBools>("filament_soluble")->values == std::vector<unsigned char>{1, 0});
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_CASE("read_cli keeps nil alongside boolean spellings in a nullable bools vector", "[Config]") {
|
||||||
|
Slic3r::DynamicPrintConfig config;
|
||||||
|
t_config_option_keys extra, keys;
|
||||||
|
const char* argv[] = {"orca-slicer", "--enable-overhang-speed=nil,yes,off"};
|
||||||
|
REQUIRE(config.read_cli(2, argv, &extra, &keys));
|
||||||
|
auto* opt = config.opt<ConfigOptionBoolsNullable>("enable_overhang_speed");
|
||||||
|
REQUIRE(opt != nullptr);
|
||||||
|
REQUIRE(opt->values.size() == 3);
|
||||||
|
REQUIRE(opt->is_nil(0));
|
||||||
|
REQUIRE(opt->values[1] == 1);
|
||||||
|
REQUIRE(opt->values[2] == 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_CASE("read_cli rejects an empty item inside a bools vector", "[Config]") {
|
||||||
|
Slic3r::DynamicPrintConfig config;
|
||||||
|
t_config_option_keys extra, keys;
|
||||||
|
const char* argv[] = {"orca-slicer", "--filament-soluble=true,,1"};
|
||||||
|
REQUIRE_FALSE(config.read_cli(2, argv, &extra, &keys));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_CASE("read_cli rejects an unknown spelling next to a valid one in a bools vector", "[Config]") {
|
||||||
|
Slic3r::DynamicPrintConfig config;
|
||||||
|
t_config_option_keys extra, keys;
|
||||||
|
const char* argv[] = {"orca-slicer", "--filament-soluble=true,affirmative"};
|
||||||
|
REQUIRE_FALSE(config.read_cli(2, argv, &extra, &keys));
|
||||||
|
}
|
||||||
|
|
||||||
|
// The normalization lives in read_cli's boolean branches, so options of other types keep the
|
||||||
|
// value verbatim - a path named "on" or a colour named "true" must not turn into "1".
|
||||||
|
TEST_CASE("read_cli leaves boolean spellings alone for non-boolean options", "[Config]") {
|
||||||
|
SECTION("string option") {
|
||||||
|
Slic3r::DynamicPrintAndCLIConfig config;
|
||||||
|
t_config_option_keys extra, keys;
|
||||||
|
const char* argv[] = {"orca-slicer", "--logfile=true"};
|
||||||
|
REQUIRE(config.read_cli(2, argv, &extra, &keys));
|
||||||
|
REQUIRE(config.opt<ConfigOptionString>("logfile")->value == "true");
|
||||||
|
}
|
||||||
|
SECTION("strings vector option") {
|
||||||
|
Slic3r::DynamicPrintConfig config;
|
||||||
|
t_config_option_keys extra, keys;
|
||||||
|
const char* argv[] = {"orca-slicer", "--filament-colour=on;off"};
|
||||||
|
REQUIRE(config.read_cli(2, argv, &extra, &keys));
|
||||||
|
REQUIRE(config.opt<ConfigOptionStrings>("filament_colour")->values == std::vector<std::string>{"on", "off"});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_CASE("read_cli treats a bare boolean flag as true without consuming the next argument", "[Config]") {
|
||||||
|
Slic3r::DynamicPrintConfig config;
|
||||||
|
t_config_option_keys extra, keys;
|
||||||
|
const char* argv[] = {"orca-slicer", "--reduce-crossing-wall", "model.3mf"};
|
||||||
|
REQUIRE(config.read_cli(3, argv, &extra, &keys));
|
||||||
|
REQUIRE(config.opt<ConfigOptionBool>("reduce_crossing_wall")->value);
|
||||||
|
REQUIRE(extra == t_config_option_keys{"model.3mf"});
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_CASE("read_cli rejects an invalid scalar numeric value", "[Config]") {
|
||||||
|
Slic3r::DynamicPrintConfig config;
|
||||||
|
t_config_option_keys extra, keys;
|
||||||
|
const char* argv[] = {"orca-slicer", "--top-shell-layers", "several"};
|
||||||
|
REQUIRE_FALSE(config.read_cli(3, argv, &extra, &keys));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_CASE("read_cli appends values when a vector option is repeated", "[Config]") {
|
||||||
|
Slic3r::DynamicPrintConfig config;
|
||||||
|
t_config_option_keys extra, keys;
|
||||||
|
const char* argv[] = {"orca-slicer", "--nozzle-temperature", "210", "--nozzle-temperature", "190,200"};
|
||||||
|
REQUIRE(config.read_cli(5, argv, &extra, &keys));
|
||||||
|
REQUIRE(config.opt<ConfigOptionInts>("nozzle_temperature")->values == std::vector<int>{210, 190, 200});
|
||||||
|
// the key is recorded once, on first use
|
||||||
|
REQUIRE(keys == t_config_option_keys{"nozzle_temperature"});
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_CASE("read_cli parses a bools vector given in the --flag=values form", "[Config]") {
|
||||||
|
Slic3r::DynamicPrintConfig config;
|
||||||
|
t_config_option_keys extra, keys;
|
||||||
|
const char* argv[] = {"orca-slicer", "--filament-soluble=1,0,1"};
|
||||||
|
REQUIRE(config.read_cli(2, argv, &extra, &keys));
|
||||||
|
REQUIRE(config.opt<ConfigOptionBools>("filament_soluble")->values == std::vector<unsigned char>{1, 0, 1});
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_CASE("read_cli rejects an invalid value inside a bools vector", "[Config]") {
|
||||||
|
Slic3r::DynamicPrintConfig config;
|
||||||
|
t_config_option_keys extra, keys;
|
||||||
|
const char* argv[] = {"orca-slicer", "--filament-soluble=1,maybe"};
|
||||||
|
REQUIRE_FALSE(config.read_cli(2, argv, &extra, &keys));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_CASE("read_cli appends true for a bare bools vector flag", "[Config]") {
|
||||||
|
Slic3r::DynamicPrintConfig config;
|
||||||
|
t_config_option_keys extra, keys;
|
||||||
|
const char* argv[] = {"orca-slicer", "--filament-soluble"};
|
||||||
|
REQUIRE(config.read_cli(2, argv, &extra, &keys));
|
||||||
|
REQUIRE(config.opt<ConfigOptionBools>("filament_soluble")->values == std::vector<unsigned char>{1});
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_CASE("read_cli splits a strings vector on semicolons and unescapes quoted items", "[Config]") {
|
||||||
|
Slic3r::DynamicPrintConfig config;
|
||||||
|
t_config_option_keys extra, keys;
|
||||||
|
const char* argv[] = {"orca-slicer", "--filament-colour", "#FF0000;\"a\\nb\";#00FF00"};
|
||||||
|
REQUIRE(config.read_cli(3, argv, &extra, &keys));
|
||||||
|
auto& values = config.opt<ConfigOptionStrings>("filament_colour")->values;
|
||||||
|
REQUIRE(values == std::vector<std::string>{"#FF0000", "a\nb", "#00FF00"});
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_CASE("read_cli rejects a strings vector with an unterminated quote", "[Config]") {
|
||||||
|
Slic3r::DynamicPrintConfig config;
|
||||||
|
t_config_option_keys extra, keys;
|
||||||
|
const char* argv[] = {"orca-slicer", "--filament-colour", "\"oops"};
|
||||||
|
REQUIRE_FALSE(config.read_cli(3, argv, &extra, &keys));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_CASE("read_cli parses a points vector in the NxM coordinate form", "[Config]") {
|
||||||
|
Slic3r::DynamicPrintConfig config;
|
||||||
|
t_config_option_keys extra, keys;
|
||||||
|
const char* argv[] = {"orca-slicer", "--printable-area", "0x0,200x0,200x200,0x200"};
|
||||||
|
REQUIRE(config.read_cli(3, argv, &extra, &keys));
|
||||||
|
auto& points = config.opt<ConfigOptionPoints>("printable_area")->values;
|
||||||
|
REQUIRE(points.size() == 4);
|
||||||
|
REQUIRE_THAT(points[1].x(), Catch::Matchers::WithinAbs(200.0, 1e-9));
|
||||||
|
REQUIRE_THAT(points[1].y(), Catch::Matchers::WithinAbs(0.0, 1e-9));
|
||||||
|
REQUIRE_THAT(points[3].x(), Catch::Matchers::WithinAbs(0.0, 1e-9));
|
||||||
|
REQUIRE_THAT(points[3].y(), Catch::Matchers::WithinAbs(200.0, 1e-9));
|
||||||
|
}
|
||||||
|
|
||||||
|
// logfile is a CLI-only option, so it needs the config type whose def pulls in cli_misc_config_def.
|
||||||
|
TEST_CASE("read_cli stores the log file path as a string", "[Config]") {
|
||||||
|
Slic3r::DynamicPrintAndCLIConfig config;
|
||||||
|
t_config_option_keys extra, keys;
|
||||||
|
const char* argv[] = {"orca-slicer", "--logfile", "orca.log"};
|
||||||
|
REQUIRE(config.read_cli(3, argv, &extra, &keys));
|
||||||
|
REQUIRE(config.opt<ConfigOptionString>("logfile")->value == "orca.log");
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_CASE("read_cli accepts nil entries for a nullable vector option", "[Config]") {
|
||||||
|
Slic3r::DynamicPrintConfig config;
|
||||||
|
t_config_option_keys extra, keys;
|
||||||
|
const char* argv[] = {"orca-slicer", "--filament-retraction-length", "nil,2.5"};
|
||||||
|
REQUIRE(config.read_cli(3, argv, &extra, &keys));
|
||||||
|
auto* opt = config.opt<ConfigOptionFloatsNullable>("filament_retraction_length");
|
||||||
|
REQUIRE(opt != nullptr);
|
||||||
|
REQUIRE(opt->values.size() == 2);
|
||||||
|
REQUIRE(opt->is_nil(0));
|
||||||
|
REQUIRE_FALSE(opt->is_nil(1));
|
||||||
|
REQUIRE_THAT(opt->values[1], Catch::Matchers::WithinAbs(2.5, 1e-9));
|
||||||
|
}
|
||||||
|
|||||||
@@ -220,6 +220,44 @@ TEST_CASE("Printer extruder count tolerates missing nozzle diameter", "[Preset][
|
|||||||
CHECK(bundle.get_printer_extruder_count() == 2);
|
CHECK(bundle.get_printer_extruder_count() == 2);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST_CASE("Selected printer uses its default or saved bed type", "[Preset][Bundle]")
|
||||||
|
{
|
||||||
|
PresetBundle bundle;
|
||||||
|
Preset& printer = add_inmemory_preset(bundle.printers, "Test Printer");
|
||||||
|
printer.is_system = true;
|
||||||
|
printer.config.option<ConfigOptionString>("printer_model")->value = "TEST-MODEL";
|
||||||
|
printer.config.option<ConfigOptionString>("printer_variant")->value = "0.4";
|
||||||
|
printer.config.option<ConfigOptionString>("default_bed_type")->value = "Engineering Plate";
|
||||||
|
|
||||||
|
AppConfig app_config;
|
||||||
|
app_config.set("curr_bed_type", std::to_string(static_cast<int>(btPTE)));
|
||||||
|
PresetBundle::PresetPreferences preferred_selection;
|
||||||
|
BedType expected_bed_type;
|
||||||
|
|
||||||
|
SECTION("New printer uses its symbolic default") {
|
||||||
|
expected_bed_type = btEP;
|
||||||
|
preferred_selection = {"TEST-MODEL", "0.4"};
|
||||||
|
}
|
||||||
|
SECTION("Re-enabled printer uses its saved selection") {
|
||||||
|
expected_bed_type = btPC;
|
||||||
|
preferred_selection = {"TEST-MODEL", "0.4"};
|
||||||
|
app_config.set_printer_setting("Test Printer", "curr_bed_type",
|
||||||
|
std::to_string(static_cast<int>(expected_bed_type)));
|
||||||
|
}
|
||||||
|
SECTION("Existing printer keeps its saved selection after presets reload") {
|
||||||
|
expected_bed_type = btPCT;
|
||||||
|
app_config.set("presets", PRESET_PRINTER_NAME, "Test Printer");
|
||||||
|
app_config.set_printer_setting("Test Printer", "curr_bed_type",
|
||||||
|
std::to_string(static_cast<int>(expected_bed_type)));
|
||||||
|
}
|
||||||
|
|
||||||
|
bundle.load_selections(app_config, preferred_selection);
|
||||||
|
bundle.export_selections(app_config);
|
||||||
|
|
||||||
|
CHECK(bundle.project_config.opt_enum<BedType>("curr_bed_type") == expected_bed_type);
|
||||||
|
CHECK(app_config.get_printer_setting("Test Printer", "curr_bed_type") == std::to_string(static_cast<int>(expected_bed_type)));
|
||||||
|
}
|
||||||
|
|
||||||
TEST_CASE("find_preset resolves a system preset's renamed_from", "[Preset][Rename]")
|
TEST_CASE("find_preset resolves a system preset's renamed_from", "[Preset][Rename]")
|
||||||
{
|
{
|
||||||
RenameTestCollection coll;
|
RenameTestCollection coll;
|
||||||
|
|||||||
Reference in New Issue
Block a user