mirror of
https://github.com/OrcaSlicer/OrcaSlicer.git
synced 2026-09-15 21:17:41 +00:00
Compare commits
7 Commits
feat/print
...
nightly-bu
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a0ada1aa88 | ||
|
|
9409598c2a | ||
|
|
7e545651bb | ||
|
|
ac3997c0d1 | ||
|
|
bd1304443c | ||
|
|
bb3a260acb | ||
|
|
2b6eb425e4 |
62
.github/workflows/build_all.yml
vendored
62
.github/workflows/build_all.yml
vendored
@@ -14,6 +14,7 @@ on:
|
||||
- 'localization/**'
|
||||
- 'resources/**'
|
||||
- ".github/workflows/build_*.yml"
|
||||
- ".github/workflows/unit_tests*.yml"
|
||||
- 'scripts/build_preset_cache.*'
|
||||
- 'scripts/flatpak/**'
|
||||
- 'scripts/msix/**'
|
||||
@@ -30,6 +31,7 @@ on:
|
||||
- '**/CMakeLists.txt'
|
||||
- 'version.inc'
|
||||
- ".github/workflows/build_*.yml"
|
||||
- ".github/workflows/unit_tests*.yml"
|
||||
- 'build_linux.sh'
|
||||
- 'build_release_vs.bat'
|
||||
- 'build_release_vs2022.bat'
|
||||
@@ -207,7 +209,7 @@ jobs:
|
||||
./validator-bin/OrcaSlicer_profile_validator -p "${{ github.workspace }}/resources/profiles" -s -l 2
|
||||
publish_test_results:
|
||||
name: Publish Test Results
|
||||
needs: [unit_tests_linux_x86_64, unit_tests_linux_aarch64, unit_tests_windows_x64, unit_tests_windows_arm64, unit_tests_macos_arm64]
|
||||
needs: [unit_tests_linux_x86_64, unit_tests_linux_aarch64, unit_tests_windows_x64, unit_tests_windows_arm64, unit_tests_macos_arm64, unit_tests_flatpak_x86_64, unit_tests_flatpak_aarch64]
|
||||
if: ${{ !cancelled() }}
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
@@ -324,9 +326,16 @@ jobs:
|
||||
sed -i '/^build-options:/a\ no-debuginfo: true\n strip: true' \
|
||||
scripts/flatpak/com.orcaslicer.OrcaSlicer.yml
|
||||
shell: bash
|
||||
- name: Inject git commit hash into Flatpak manifest
|
||||
# flatpak-builder reuses a module from its cache when the definition and
|
||||
# sources are unchanged, so a re-run of the same commit would skip the
|
||||
# OrcaSlicer module and ship no test asset. A per-run value in that module's
|
||||
# env keeps it rebuilding; orca_deps stays cached, and the compiler cache
|
||||
# still serves the rebuild.
|
||||
- name: Inject commit hash and flatpak-builder cache buster into Flatpak manifest
|
||||
env:
|
||||
flatpak_builder_cache_buster: ${{ github.run_id }}-${{ github.run_attempt }}
|
||||
run: |
|
||||
sed -i "/name: OrcaSlicer/{n;s|buildsystem: simple|buildsystem: simple\n build-options:\n env:\n git_commit_hash: \"$git_commit_hash\"|}" \
|
||||
sed -i "/name: OrcaSlicer/{n;s|buildsystem: simple|buildsystem: simple\n build-options:\n env:\n flatpak_builder_cache_buster: \"$flatpak_builder_cache_buster\"\n git_commit_hash: \"$git_commit_hash\"|}" \
|
||||
scripts/flatpak/com.orcaslicer.OrcaSlicer.yml
|
||||
shell: bash
|
||||
# flatpak-builder's --ccache only wraps cc and gcc, and the manifest builds
|
||||
@@ -372,6 +381,10 @@ jobs:
|
||||
save-cache: false
|
||||
arch: ${{ matrix.variant.arch }}
|
||||
upload-artifact: false
|
||||
# run-tests fires the module's build-only test-commands; keep-build-dirs
|
||||
# retains the binaries for the packaging step below.
|
||||
run-tests: true
|
||||
keep-build-dirs: true
|
||||
# The build has just touched everything it can use, so an object untouched
|
||||
# for a week is dead, usually orphaned by a flag change.
|
||||
- name: Compiler cache statistics
|
||||
@@ -425,3 +438,46 @@ jobs:
|
||||
asset_name: OrcaSlicer-Linux-flatpak_nightly${{ env.nightly_suffix }}_${{ matrix.variant.arch }}.flatpak
|
||||
asset_content_type: application/octet-stream
|
||||
max_releases: 1 # optional, if there are more releases than this matching the asset_name, the oldest ones are going to be deleted
|
||||
# The asset is /app (the exes link it at runtime) plus the build tree
|
||||
# slimmed to what ctest needs.
|
||||
- name: Package flatpak test asset
|
||||
shell: bash
|
||||
run: |
|
||||
d=$(ls -d .flatpak-builder/build/OrcaSlicer-* | tail -1)
|
||||
find "$d/build_flatpak" -mindepth 1 -maxdepth 1 ! -name tests -exec rm -rf {} +
|
||||
# Strip debug info (the SDK builds with -g, only the app gets stripped);
|
||||
# the bounds checks are compiled in, so a stripped exe still catches them.
|
||||
find "$d/build_flatpak/tests" -type f -perm -u+x -exec strip --strip-unneeded {} + 2>/dev/null || true
|
||||
# At runtime the tests read tests/ (TEST_DATA_DIR), scripts/, and under
|
||||
# resources/ the shipped profiles (PROFILES_DIR) and the printers/ maps.
|
||||
find "$d" -mindepth 1 -maxdepth 1 -type d \
|
||||
! -name tests ! -name build_flatpak ! -name scripts ! -name resources -exec rm -rf {} +
|
||||
find "$d/resources" -mindepth 1 -maxdepth 1 ! -name profiles ! -name printers -exec rm -rf {} +
|
||||
tar -cf flatpak-test-asset.tar flatpak_app "$d"
|
||||
- name: Upload flatpak test asset
|
||||
uses: actions/upload-artifact@v7
|
||||
with:
|
||||
name: ${{ github.sha }}-flatpak-tests-${{ matrix.variant.arch }}
|
||||
path: flatpak-test-asset.tar
|
||||
retention-days: 1
|
||||
# keep-build-dirs would otherwise land in the flatpak-builder cache saved post-job.
|
||||
- name: Drop the kept build dirs before the flatpak-builder cache saves
|
||||
if: always()
|
||||
shell: bash
|
||||
run: rm -rf .flatpak-builder/build
|
||||
unit_tests_flatpak_x86_64:
|
||||
name: Flatpak x86_64
|
||||
needs: flatpak
|
||||
if: ${{ !cancelled() && success() }}
|
||||
uses: ./.github/workflows/unit_tests_flatpak.yml
|
||||
with:
|
||||
os: ubuntu-24.04
|
||||
artifact: ${{ github.sha }}-flatpak-tests-x86_64
|
||||
unit_tests_flatpak_aarch64:
|
||||
name: Flatpak aarch64
|
||||
needs: flatpak
|
||||
if: ${{ !cancelled() && success() }}
|
||||
uses: ./.github/workflows/unit_tests_flatpak.yml
|
||||
with:
|
||||
os: ubuntu-24.04-arm
|
||||
artifact: ${{ github.sha }}-flatpak-tests-aarch64
|
||||
|
||||
67
.github/workflows/unit_tests_flatpak.yml
vendored
Normal file
67
.github/workflows/unit_tests_flatpak.yml
vendored
Normal file
@@ -0,0 +1,67 @@
|
||||
name: Flatpak Unit Tests
|
||||
|
||||
# Run the flatpak build's test asset inside the sandbox, once per arch. The
|
||||
# GNOME SDK's _GLIBCXX_ASSERTIONS gives a bounds-checked STL that catches
|
||||
# out-of-bounds reads no other test leg does.
|
||||
on:
|
||||
workflow_call:
|
||||
inputs:
|
||||
os:
|
||||
required: true
|
||||
type: string
|
||||
artifact:
|
||||
description: Test asset uploaded by the flatpak build leg
|
||||
required: true
|
||||
type: string
|
||||
|
||||
jobs:
|
||||
unit_tests_flatpak:
|
||||
name: Flatpak Unit Tests
|
||||
runs-on: ${{ inputs.os }}
|
||||
container:
|
||||
image: ghcr.io/flathub-infra/flatpak-github-actions:gnome-50
|
||||
options: --privileged
|
||||
steps:
|
||||
- name: Restore test asset
|
||||
uses: actions/download-artifact@v8
|
||||
with:
|
||||
name: ${{ inputs.artifact }}
|
||||
- name: Run unit tests (bounds-checked sandbox)
|
||||
timeout-minutes: 20
|
||||
shell: bash
|
||||
run: |
|
||||
tar -xf flatpak-test-asset.tar
|
||||
# Recreate the stable module symlink so /run/build/OrcaSlicer resolves.
|
||||
d=$(ls -d .flatpak-builder/build/OrcaSlicer-* | tail -1)
|
||||
ln -sfn "$(basename "$d")" .flatpak-builder/build/OrcaSlicer
|
||||
# The runtime + SDK + the llvm extension the app metadata references,
|
||||
# which `flatpak build` mounts; best-effort, the image may have them.
|
||||
flatpak remote-add --if-not-exists --user flathub https://flathub.org/repo/flathub.flatpakrepo
|
||||
flatpak install --user -y --noninteractive flathub \
|
||||
org.gnome.Platform//50 org.gnome.Sdk//50 org.freedesktop.Sdk.Extension.llvm21//25.08 || true
|
||||
# `flatpak build` uses bwrap (no rofiles-fuse, which this container
|
||||
# rejects); bind-mount the build tree so the baked TEST_DATA_DIR resolves.
|
||||
flatpak build --die-with-parent --share=network \
|
||||
--bind-mount=/run/build="$PWD/.flatpak-builder/build" \
|
||||
flatpak_app \
|
||||
bash -c 'cd /run/build/OrcaSlicer && scripts/run_unit_tests.sh build_flatpak/tests'
|
||||
- name: Collect test results
|
||||
if: always()
|
||||
shell: bash
|
||||
run: |
|
||||
d=$(ls -d .flatpak-builder/build/OrcaSlicer-* 2>/dev/null | tail -1 || true)
|
||||
[ -n "$d" ] && [ -f "$d/ctest_results.xml" ] && cp "$d/ctest_results.xml" ctest_results.xml || true
|
||||
- name: Upload Test Results
|
||||
if: always()
|
||||
uses: actions/upload-artifact@v7
|
||||
with:
|
||||
name: test-results-${{ inputs.artifact }}
|
||||
path: ctest_results.xml
|
||||
retention-days: 5
|
||||
if-no-files-found: warn
|
||||
- name: Delete Test Asset
|
||||
if: success()
|
||||
uses: geekyeggo/delete-artifact@v6
|
||||
with:
|
||||
name: ${{ inputs.artifact }}
|
||||
failOnError: false
|
||||
@@ -64,16 +64,16 @@ ctest --test-dir ./tests/fff_print
|
||||
- Keep code concise and clear. Manually simplify AI generated bloated codes before review.
|
||||
- Include targeted tests or documented verification for behavior changes, especially in slicing logic, profiles, formats, and GUI defaults.
|
||||
- For profile changes (`resources/profiles/<Vendor>/**`), check that `version` in the sibling `resources/profiles/<Vendor>.json` was bumped.
|
||||
- For translation changes (`localization/i18n/**/*.po`), check that recurring terms match the [Localization glossary](https://github.com/OrcaSlicer/OrcaSlicer_WIKI/blob/main/guides/localization_glossary.md) for that language.
|
||||
- For translation changes (`localization/i18n/**/*.po`), check that recurring terms match the [Localization glossary](https://github.com/OrcaSlicer/OrcaSlicer_WIKI/blob/main/developer_reference/localization_glossary.md) for that language.
|
||||
|
||||
## Localization & translations
|
||||
|
||||
Catalogs live in `localization/i18n/<lang>/OrcaSlicer_<lang>.po`; the template is `OrcaSlicer.pot`.
|
||||
See the [Localization guide](https://github.com/OrcaSlicer/OrcaSlicer_WIKI/blob/main/guides/localization_guide.md) for the human-facing version of these principles.
|
||||
See the [Localization guide](https://github.com/OrcaSlicer/OrcaSlicer_WIKI/blob/main/developer_reference/localization_guide.md) for the human-facing version of these principles.
|
||||
|
||||
### Terminology
|
||||
|
||||
- Use the [Localization glossary](https://github.com/OrcaSlicer/OrcaSlicer_WIKI/blob/main/guides/localization_glossary.md) as the source of truth for recurring terms, so the same English term is always rendered the same way within a language, and terms that must stay in English (brand/product names, acronyms, materials, file formats, G-code tokens, macros/variables/identifiers) are not translated.
|
||||
- Use the [Localization glossary](https://github.com/OrcaSlicer/OrcaSlicer_WIKI/blob/main/developer_reference/localization_glossary.md) as the source of truth for recurring terms, so the same English term is always rendered the same way within a language, and terms that must stay in English (brand/product names, acronyms, materials, file formats, G-code tokens, macros/variables/identifiers) are not translated.
|
||||
- If a term's established translation changes, update both the affected `.po` files and the glossary (`localization_glossary.tsv`, then regenerate) so they stay in sync.
|
||||
- Translate the *meaning*, not the words. Check what the string actually controls before translating it — English reuses one word for different things. `Flow ratio` (multiplier), `Flow Rate` (throughput) and `Flow Dynamics` (pressure compensation) are three different terms; `extruder` may mean the toolhead, the feeder motor, or the nozzle depending on the string.
|
||||
- Reuse one template per recurring message shape (`Failed to connect to …`, `Are you sure you want to …?`), even where the English wording varies.
|
||||
|
||||
12
deps/python3/arm64-unicodectype.props
vendored
Normal file
12
deps/python3/arm64-unicodectype.props
vendored
Normal file
@@ -0,0 +1,12 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Compiles Objects/unicodectype.c without optimisation. VS 2026's ARM64 code
|
||||
generator needs about 27 GB for _PyUnicode_ToNumeric, a switch with 1951
|
||||
cases. CPython has the same workaround (python/cpython#153668). -->
|
||||
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup>
|
||||
<ClCompile Update="..\Objects\unicodectype.c">
|
||||
<Optimization>Disabled</Optimization>
|
||||
<WholeProgramOptimization>false</WholeProgramOptimization>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
12
deps/python3/python3.cmake
vendored
12
deps/python3/python3.cmake
vendored
@@ -88,8 +88,18 @@ if(WIN32)
|
||||
list(APPEND _python_env_args "PreferredToolArchitecture=${_python_tool_arch}")
|
||||
endif()
|
||||
|
||||
# MSBuild reads extra switches from PCbuild/msbuild.rsp.
|
||||
set(_python_rsp "/p:PlatformToolset=${_python_platform_toolset}\n")
|
||||
# VS 2026's ARM64 code generator needs about 27 GB for one function in
|
||||
# Objects/unicodectype.c (python/cpython#153668); the property sheet compiles
|
||||
# that file without optimisation.
|
||||
if(_python_pcbuild_platform STREQUAL "ARM64")
|
||||
file(TO_NATIVE_PATH "${CMAKE_CURRENT_LIST_DIR}/arm64-unicodectype.props" _python_arm64_props)
|
||||
string(APPEND _python_rsp "/p:ForceImportAfterCppTargets=\"${_python_arm64_props}\"\n")
|
||||
endif()
|
||||
file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/python3-msbuild.rsp" "${_python_rsp}")
|
||||
set(_conf_cmd
|
||||
cmd /c "echo /p:PlatformToolset=${_python_platform_toolset}>PCbuild\\msbuild.rsp"
|
||||
${CMAKE_COMMAND} -E copy "${CMAKE_CURRENT_BINARY_DIR}/python3-msbuild.rsp" <SOURCE_DIR>/PCbuild/msbuild.rsp
|
||||
)
|
||||
set(_build_cmd
|
||||
${CMAKE_COMMAND} -E env ${_python_env_args}
|
||||
|
||||
@@ -75,7 +75,7 @@ documentation_link = https://www.orcaslicer.com/wiki/material_temperatures#print
|
||||
|
||||
[hint:Calibration]
|
||||
text = Calibration\nDid you know that calibrating your printer can do wonders? Check out our beloved calibration solution in OrcaSlicer.
|
||||
documentation_link = https://www.orcaslicer.com/wiki/calibration
|
||||
documentation_link = https://www.orcaslicer.com/wiki/calibration_guide
|
||||
|
||||
[hint:Auxiliary fan]
|
||||
text = Auxiliary fan\nDid you know that OrcaSlicer supports Auxiliary part cooling fan?
|
||||
|
||||
@@ -378,6 +378,17 @@ modules:
|
||||
- cmake --build build_flatpak --target generate_system_cache -j$FLATPAK_BUILDER_N_JOBS
|
||||
- ./scripts/build_preset_cache.sh -n -b build_flatpak /app/share/OrcaSlicer/profiles
|
||||
|
||||
# Built (not run) here via the action's run-tests, then shipped to a separate
|
||||
# test job. Only the test sources compile; nothing installs to /app.
|
||||
test-commands:
|
||||
- cmake . -B build_flatpak -DBUILD_TESTS=ON
|
||||
# A suite missing from this list fails the leg loudly, since ctest registers a
|
||||
# <target>_NOT_BUILT test for it. (tests/all is a Ninja subdirectory target and
|
||||
# this build uses the default Makefile generator, so it is not available here.)
|
||||
- cmake --build build_flatpak -j"${FLATPAK_BUILDER_N_JOBS:-$(nproc)}" --target
|
||||
libslic3r_tests fff_print_tests sla_print_tests libnest2d_tests slic3rutils_tests
|
||||
filament_group_tests
|
||||
|
||||
cleanup:
|
||||
- /include
|
||||
|
||||
@@ -414,6 +425,10 @@ modules:
|
||||
- type: dir
|
||||
path: ../../localization
|
||||
dest: localization
|
||||
# For the post-build unit-test step (BUILD_TESTS=ON); not built by the app.
|
||||
- type: dir
|
||||
path: ../../tests
|
||||
dest: tests
|
||||
|
||||
- type: file
|
||||
path: ../../CMakeLists.txt
|
||||
@@ -427,6 +442,9 @@ modules:
|
||||
- type: file
|
||||
path: ../build_preset_cache.sh
|
||||
dest: scripts
|
||||
- type: file
|
||||
path: ../run_unit_tests.sh
|
||||
dest: scripts
|
||||
|
||||
# AppData metainfo for GNOME Software & Co.
|
||||
- type: file
|
||||
|
||||
@@ -3555,7 +3555,7 @@ void GCode::_do_export(Print& print, GCodeOutputStream &file, ThumbnailsGenerato
|
||||
|
||||
auto used_filaments = print.get_slice_used_filaments(false);
|
||||
this->placeholder_parser().set("is_all_bbl_filament", std::all_of(used_filaments.begin(), used_filaments.end(), [&](auto idx) {
|
||||
return m_config.filament_vendor.values[idx] == "Bambu Lab";
|
||||
return m_config.filament_vendor.get_at(idx) == "Bambu Lab";
|
||||
}));
|
||||
|
||||
//add during_print_exhaust_fan_speed
|
||||
@@ -3572,7 +3572,7 @@ void GCode::_do_export(Print& print, GCodeOutputStream &file, ThumbnailsGenerato
|
||||
this->placeholder_parser().set("outer_wall_volumetric_speed", new ConfigOptionFloat(outer_wall_volumetric_speed));
|
||||
|
||||
auto first_layer_filaments = print.get_slice_used_filaments(true);
|
||||
bool has_tpu_in_first_layer = std::any_of(first_layer_filaments.begin(), first_layer_filaments.end(), [&](unsigned int idx) { return m_config.filament_type.values[idx] == "TPU"; });
|
||||
bool has_tpu_in_first_layer = std::any_of(first_layer_filaments.begin(), first_layer_filaments.end(), [&](unsigned int idx) { return m_config.filament_type.get_at(idx) == "TPU"; });
|
||||
this->placeholder_parser().set("has_tpu_in_first_layer", new ConfigOptionBool(has_tpu_in_first_layer));
|
||||
|
||||
if (print.calib_params().mode == CalibMode::Calib_PA_Line) {
|
||||
@@ -9474,12 +9474,14 @@ std::string GCode::set_extruder(unsigned int new_filament_id, double print_z, bo
|
||||
if (old_filament_id_in_new_extruder == -1)
|
||||
wipe_volume = 0;
|
||||
else {
|
||||
wipe_volume = flush_matrix[old_filament_id_in_new_extruder * number_of_extruders + new_filament_id];
|
||||
size_t flush_idx = size_t(old_filament_id_in_new_extruder) * number_of_extruders + new_filament_id;
|
||||
wipe_volume = flush_idx < flush_matrix.size() ? flush_matrix[flush_idx] : 0.f;
|
||||
wipe_volume *= m_config.flush_multiplier.get_at(new_extruder_id);
|
||||
}
|
||||
}
|
||||
else {
|
||||
wipe_volume = flush_matrix[old_filament_id * number_of_extruders + new_filament_id];
|
||||
size_t flush_idx = size_t(old_filament_id) * number_of_extruders + new_filament_id;
|
||||
wipe_volume = flush_idx < flush_matrix.size() ? flush_matrix[flush_idx] : 0.f;
|
||||
wipe_volume *= m_config.flush_multiplier.get_at(new_extruder_id); // if is multi_extruder only use the fist extruder matrix
|
||||
}
|
||||
wipe_volume = std::max(0.f, wipe_volume-grab_purge_volume);
|
||||
|
||||
@@ -7596,8 +7596,8 @@ void GCodeProcessor::update_slice_warnings()
|
||||
if (used_filaments[idx] < m_result.required_nozzle_HRC.size())
|
||||
filament_hrc = m_result.required_nozzle_HRC[used_filaments[idx]];
|
||||
|
||||
int filament_extruder_id = m_filament_maps[used_filaments[idx]];
|
||||
int extruder_hrc = nozzle_hrc_lists[filament_extruder_id];
|
||||
int filament_extruder_id = used_filaments[idx] < m_filament_maps.size() ? m_filament_maps[used_filaments[idx]] : -1;
|
||||
int extruder_hrc = (filament_extruder_id >= 0 && (size_t) filament_extruder_id < nozzle_hrc_lists.size()) ? nozzle_hrc_lists[filament_extruder_id] : 0;
|
||||
|
||||
BOOST_LOG_TRIVIAL(debug) << __FUNCTION__ << boost::format(": Check HRC: filament:%1%, hrc=%2%, extruder:%3%, hrc:%4%") % used_filaments[idx] % filament_hrc % filament_extruder_id % extruder_hrc;
|
||||
|
||||
|
||||
@@ -1488,10 +1488,10 @@ static FilamentGroupContext build_filament_group_context(
|
||||
|
||||
auto machine_filament_info = build_machine_filaments(print->get_extruder_filament_info(), extruder_ams_counts, ignore_ext_filament);
|
||||
|
||||
std::vector<std::string> filament_types = print_config.filament_type.values;
|
||||
std::vector<std::string> filament_colours = print_config.filament_colour.values;
|
||||
std::vector<unsigned char> filament_is_support = print_config.filament_is_support.values;
|
||||
std::vector<std::string> filament_ids = print_config.filament_ids.values;
|
||||
// The grouping code walks filament_ids and indexes filament_info by the same position.
|
||||
std::vector<std::string> filament_ids = print_config.filament_ids.values;
|
||||
if (filament_ids.size() > filament_nums)
|
||||
filament_ids.resize(filament_nums);
|
||||
|
||||
FGMode fg_mode = mode == FilamentMapMode::fmmAutoForMatch ? FGMode::MatchMode : FGMode::FlushMode;
|
||||
context.model_info.flush_matrix = std::move(nozzle_flush_mtx);
|
||||
@@ -1500,11 +1500,14 @@ static FilamentGroupContext build_filament_group_context(
|
||||
context.model_info.filament_ids = filament_ids;
|
||||
context.model_info.unprintable_volumes = unprintable_volumes;
|
||||
|
||||
for (size_t idx = 0; idx < filament_types.size(); ++idx) {
|
||||
// Consumers index filament_info by filament id, so it must span the filament count: a partial
|
||||
// or legacy config can leave any of these arrays short, and get_at clamps.
|
||||
context.model_info.filament_info.reserve(filament_nums);
|
||||
for (size_t idx = 0; idx < filament_nums; ++idx) {
|
||||
FilamentGroupUtils::FilamentInfo info;
|
||||
info.color = filament_colours[idx];
|
||||
info.type = filament_types[idx];
|
||||
info.is_support = filament_is_support[idx];
|
||||
info.color = print_config.filament_colour.get_at(idx);
|
||||
info.type = print_config.filament_type.get_at(idx);
|
||||
info.is_support = print_config.filament_is_support.get_at(idx);
|
||||
context.model_info.filament_info.emplace_back(std::move(info));
|
||||
}
|
||||
|
||||
|
||||
@@ -1349,7 +1349,7 @@ public:
|
||||
// flavor it reaches understands, not the zero dwell the other flavors flush with.
|
||||
buffer += "M400\n";
|
||||
buffer += "M104";
|
||||
if (target_extruder != -1)
|
||||
if (target_extruder != -1 && target_extruder < int(m_physical_extruder_map.size()))
|
||||
buffer += (" T" + std::to_string(m_physical_extruder_map[target_extruder]));
|
||||
buffer += " S" + std::to_string(target_temp) + " N0"; // N0 means the gcode is generated by slicer
|
||||
if (!comment.empty()) buffer += " ;" + comment;
|
||||
@@ -1361,7 +1361,7 @@ public:
|
||||
WipeTowerWriter &format_line_M109(int target_temp, int target_extruder, const std::string &comment = std::string())
|
||||
{
|
||||
std::string buffer = "M109";
|
||||
if (target_extruder != -1)
|
||||
if (target_extruder != -1 && target_extruder < int(m_physical_extruder_map.size()))
|
||||
buffer += (" T" + std::to_string(m_physical_extruder_map[target_extruder]));
|
||||
buffer += " S" + std::to_string(target_temp) + " N0"; // N0 means the gcode is generated by slicer
|
||||
if (!comment.empty()) buffer += " ;" + comment;
|
||||
@@ -3309,7 +3309,7 @@ void WipeTower::get_wall_skip_points(const WipeTowerInfo &layer, int layer_id)
|
||||
if (!cur_block_depth.count(m_filpar[new_filament].category)) cur_block_depth[m_filpar[new_filament].category] = block->start_depth;
|
||||
process_depth = cur_block_depth[m_filpar[new_filament].category];
|
||||
if (is_need_ramming(new_filament, old_filament, layer_id)) {
|
||||
if (m_filament_categories[new_filament] == m_filament_categories[old_filament])
|
||||
if (get_filament_category(new_filament) == get_filament_category(old_filament))
|
||||
process_depth += nozzle_change_depth;
|
||||
else {
|
||||
if (!cur_block_depth.count(m_filpar[old_filament].category)) {
|
||||
@@ -4783,7 +4783,7 @@ int WipeTower::get_wall_filament_for_all_layer()
|
||||
int filament_id = -1;
|
||||
int filament_count = 0;
|
||||
for (auto iter = filament_counts.begin(); iter != filament_counts.end(); ++iter) {
|
||||
if (m_filament_categories[iter->first] == selected_category && iter->second > filament_count) {
|
||||
if (get_filament_category(iter->first) == selected_category && iter->second > filament_count) {
|
||||
filament_id = iter->first;
|
||||
filament_count = iter->second;
|
||||
}
|
||||
|
||||
@@ -665,7 +665,7 @@ PublishSettingsDialog::PublishSettingsDialog(wxWindow* parent,
|
||||
};
|
||||
wxBoxSizer* links_sizer = new wxBoxSizer(wxVERTICAL);
|
||||
links_sizer->Add(make_link(_L("Publish 3MF Wiki"), "https://www.orcaslicer.com/wiki/publishing_3mf/publish_3mf.html"), 0, wxALIGN_LEFT);
|
||||
links_sizer->Add(make_link(_L("Publish 3MF Video Guide"), "https://www.youtube.com/@OfficialOrcaSlicer/videos"), 0,
|
||||
links_sizer->Add(make_link(_L("Publish 3MF Video Guide"), "https://www.youtube.com/watch?v=-xt1N29UIOg"), 0,
|
||||
wxTOP | wxALIGN_LEFT, FromDIP(4));
|
||||
|
||||
wxBoxSizer* footer = new wxBoxSizer(wxHORIZONTAL);
|
||||
|
||||
@@ -163,6 +163,50 @@ TEST_CASE("H2C multi-nozzle: filaments get distinct nozzles on the 6-nozzle extr
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE("Grouping context spans the filament count with mis-sized config arrays", "[ToolOrdering][H2C]")
|
||||
{
|
||||
// FilamentGroup indexes the grouping context's filament_info by filament id, so a short
|
||||
// per-filament array must not shorten it: the reads run off the end.
|
||||
DynamicPrintConfig config = DynamicPrintConfig::full_print_config();
|
||||
// Single 6-nozzle extruder: opens the grouping engine without needing a BBL multi-extruder.
|
||||
config.option<ConfigOptionFloats>("nozzle_diameter", true)->values = {0.4};
|
||||
config.option<ConfigOptionIntsNullable>("extruder_max_nozzle_count", true)->values = {6};
|
||||
config.option<ConfigOptionStrings>("extruder_nozzle_stats", true)->values = {"Standard#6"};
|
||||
|
||||
// Four filaments, with filament_type / filament_is_support left short on purpose.
|
||||
config.option<ConfigOptionStrings>("filament_colour", true)->values = {"#FF0000", "#00FF00", "#0000FF", "#FFFF00"};
|
||||
config.option<ConfigOptionStrings>("filament_type", true)->values = {"PLA"};
|
||||
config.option<ConfigOptionBools>("filament_is_support", true)->values = {0};
|
||||
config.option<ConfigOptionFloats>("filament_diameter", true)->values = {1.75, 1.75, 1.75, 1.75};
|
||||
config.option<ConfigOptionInts>("filament_map", true)->values = {1, 1, 1, 1};
|
||||
config.option<ConfigOptionFloats>("flush_volumes_matrix", true)->values = std::vector<double>(16, 140.);
|
||||
config.option<ConfigOptionFloats>("flush_multiplier", true)->values = {1.};
|
||||
|
||||
Model model;
|
||||
model.add_object("cube", "", make_cube(20, 20, 20))->add_instance();
|
||||
|
||||
Print print;
|
||||
print.apply(model, config);
|
||||
// apply() does not pad the per-filament arrays, so the mis-sizing survives into the engine.
|
||||
REQUIRE(print.config().filament_type.values.size() < print.config().filament_colour.values.size());
|
||||
|
||||
std::vector<std::vector<unsigned int>> layer_filaments = {{0, 1}, {1, 2}, {2, 3}};
|
||||
|
||||
SECTION("short per-filament arrays still yield one entry per filament") {
|
||||
auto result = ToolOrdering::get_recommended_filament_maps(layer_filaments, &print, FilamentMapMode::fmmAutoForFlush, {}, {});
|
||||
REQUIRE(result.get_extruder_map(false).size() == 4);
|
||||
for (int f = 0; f < 4; ++f)
|
||||
REQUIRE(result.get_extruder_id(f) == 0);
|
||||
}
|
||||
|
||||
SECTION("filament_ids longer than the filament count is truncated, not paired past the end") {
|
||||
config.option<ConfigOptionStrings>("filament_ids", true)->values = {"a", "b", "c", "d", "e", "f"};
|
||||
print.apply(model, config);
|
||||
auto result = ToolOrdering::get_recommended_filament_maps(layer_filaments, &print, FilamentMapMode::fmmAutoForFlush, {}, {});
|
||||
REQUIRE(result.get_extruder_map(false).size() == 4);
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE("H2C dynamic selector: per-layer nozzle ids reach the g-code surface", "[ToolOrdering][H2C][Dynamic]")
|
||||
{
|
||||
// The per-layer regroup engine
|
||||
|
||||
@@ -55,6 +55,18 @@ elseif (APPLE)
|
||||
COMMENT "Copying Python runtime for macOS plugin host API tests"
|
||||
VERBATIM
|
||||
)
|
||||
elseif (FLATPAK)
|
||||
# Same <testdir>/python home as WIN32/APPLE; symlink since /app/libpython
|
||||
# already ships in the flatpak (the test exe links libpython3.12.so from it).
|
||||
add_custom_command(TARGET ${_TEST_NAME}_tests POST_BUILD
|
||||
COMMAND ${CMAKE_COMMAND} -E rm -rf
|
||||
"$<TARGET_FILE_DIR:${_TEST_NAME}_tests>/python"
|
||||
COMMAND ${CMAKE_COMMAND} -E create_symlink
|
||||
"${CMAKE_PREFIX_PATH}/libpython"
|
||||
"$<TARGET_FILE_DIR:${_TEST_NAME}_tests>/python"
|
||||
COMMENT "Linking Python runtime for flatpak plugin host API tests"
|
||||
VERBATIM
|
||||
)
|
||||
endif()
|
||||
|
||||
orcaslicer_discover_tests(${_TEST_NAME}_tests)
|
||||
|
||||
Reference in New Issue
Block a user