mirror of
https://github.com/OrcaSlicer/OrcaSlicer.git
synced 2026-08-31 22:06:59 +00:00
Merge branch 'main' into feat/plugin-feature
This commit is contained in:
2
.github/workflows/auto-close-duplicates.yml
vendored
2
.github/workflows/auto-close-duplicates.yml
vendored
@@ -15,7 +15,7 @@ jobs:
|
|||||||
|
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout repository
|
- name: Checkout repository
|
||||||
uses: actions/checkout@v6
|
uses: actions/checkout@v7
|
||||||
|
|
||||||
- name: Setup Bun
|
- name: Setup Bun
|
||||||
uses: oven-sh/setup-bun@v2
|
uses: oven-sh/setup-bun@v2
|
||||||
|
|||||||
@@ -29,7 +29,7 @@ jobs:
|
|||||||
|
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout repository
|
- name: Checkout repository
|
||||||
uses: actions/checkout@v6
|
uses: actions/checkout@v7
|
||||||
|
|
||||||
- name: Setup Bun
|
- name: Setup Bun
|
||||||
uses: oven-sh/setup-bun@v2
|
uses: oven-sh/setup-bun@v2
|
||||||
|
|||||||
8
.github/workflows/build_all.yml
vendored
8
.github/workflows/build_all.yml
vendored
@@ -131,7 +131,7 @@ jobs:
|
|||||||
if: ${{ !cancelled() && success() }}
|
if: ${{ !cancelled() && success() }}
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout
|
- name: Checkout
|
||||||
uses: actions/checkout@v6
|
uses: actions/checkout@v7
|
||||||
with:
|
with:
|
||||||
sparse-checkout: |
|
sparse-checkout: |
|
||||||
.github
|
.github
|
||||||
@@ -204,7 +204,7 @@ jobs:
|
|||||||
- name: "Remove unneeded stuff to free disk space"
|
- name: "Remove unneeded stuff to free disk space"
|
||||||
run:
|
run:
|
||||||
rm -rf /usr/local/lib/android/* /usr/share/dotnet/* /opt/ghc1/* "/usr/local/share/boost1/*" /opt/hostedtoolcache1/*
|
rm -rf /usr/local/lib/android/* /usr/share/dotnet/* /opt/ghc1/* "/usr/local/share/boost1/*" /opt/hostedtoolcache1/*
|
||||||
- uses: actions/checkout@v6
|
- uses: actions/checkout@v7
|
||||||
- name: Get the version and date
|
- name: Get the version and date
|
||||||
run: |
|
run: |
|
||||||
ver_pure=$(grep 'set(SoftFever_VERSION' version.inc | cut -d '"' -f2)
|
ver_pure=$(grep 'set(SoftFever_VERSION' version.inc | cut -d '"' -f2)
|
||||||
@@ -223,14 +223,14 @@ jobs:
|
|||||||
# Manage flatpak-builder cache externally so PRs restore but never upload
|
# Manage flatpak-builder cache externally so PRs restore but never upload
|
||||||
- name: Restore flatpak-builder cache
|
- name: Restore flatpak-builder cache
|
||||||
if: github.event_name == 'pull_request'
|
if: github.event_name == 'pull_request'
|
||||||
uses: actions/cache/restore@v5
|
uses: actions/cache/restore@v6
|
||||||
with:
|
with:
|
||||||
path: .flatpak-builder
|
path: .flatpak-builder
|
||||||
key: flatpak-builder-${{ matrix.variant.arch }}-${{ github.event.pull_request.base.sha }}
|
key: flatpak-builder-${{ matrix.variant.arch }}-${{ github.event.pull_request.base.sha }}
|
||||||
restore-keys: flatpak-builder-${{ matrix.variant.arch }}-
|
restore-keys: flatpak-builder-${{ matrix.variant.arch }}-
|
||||||
- name: Save/restore flatpak-builder cache
|
- name: Save/restore flatpak-builder cache
|
||||||
if: github.event_name != 'pull_request'
|
if: github.event_name != 'pull_request'
|
||||||
uses: actions/cache@v5
|
uses: actions/cache@v6
|
||||||
with:
|
with:
|
||||||
path: .flatpak-builder
|
path: .flatpak-builder
|
||||||
key: flatpak-builder-${{ matrix.variant.arch }}-${{ github.sha }}
|
key: flatpak-builder-${{ matrix.variant.arch }}-${{ github.sha }}
|
||||||
|
|||||||
4
.github/workflows/build_check_cache.yml
vendored
4
.github/workflows/build_check_cache.yml
vendored
@@ -26,7 +26,7 @@ jobs:
|
|||||||
valid-cache: ${{ steps.cache_deps.outputs.cache-hit }}
|
valid-cache: ${{ steps.cache_deps.outputs.cache-hit }}
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout
|
- name: Checkout
|
||||||
uses: actions/checkout@v6
|
uses: actions/checkout@v7
|
||||||
with:
|
with:
|
||||||
lfs: 'false'
|
lfs: 'false'
|
||||||
|
|
||||||
@@ -46,7 +46,7 @@ jobs:
|
|||||||
|
|
||||||
- name: load cache
|
- name: load cache
|
||||||
id: cache_deps
|
id: cache_deps
|
||||||
uses: actions/cache@v5
|
uses: actions/cache@v6
|
||||||
with:
|
with:
|
||||||
path: ${{ steps.set_outputs.outputs.cache-path }}
|
path: ${{ steps.set_outputs.outputs.cache-path }}
|
||||||
key: ${{ steps.set_outputs.outputs.cache-key }}
|
key: ${{ steps.set_outputs.outputs.cache-key }}
|
||||||
|
|||||||
4
.github/workflows/build_deps.yml
vendored
4
.github/workflows/build_deps.yml
vendored
@@ -34,12 +34,12 @@ jobs:
|
|||||||
|
|
||||||
# Setup the environment
|
# Setup the environment
|
||||||
- name: Checkout
|
- name: Checkout
|
||||||
uses: actions/checkout@v6
|
uses: actions/checkout@v7
|
||||||
with:
|
with:
|
||||||
lfs: 'false'
|
lfs: 'false'
|
||||||
|
|
||||||
- name: load cached deps
|
- name: load cached deps
|
||||||
uses: actions/cache@v5
|
uses: actions/cache@v6
|
||||||
with:
|
with:
|
||||||
path: ${{ inputs.cache-path }}
|
path: ${{ inputs.cache-path }}
|
||||||
key: ${{ inputs.cache-key }}
|
key: ${{ inputs.cache-key }}
|
||||||
|
|||||||
4
.github/workflows/build_orca.yml
vendored
4
.github/workflows/build_orca.yml
vendored
@@ -37,13 +37,13 @@ jobs:
|
|||||||
|
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout
|
- name: Checkout
|
||||||
uses: actions/checkout@v6
|
uses: actions/checkout@v7
|
||||||
with:
|
with:
|
||||||
lfs: 'false'
|
lfs: 'false'
|
||||||
|
|
||||||
- name: load cached deps
|
- name: load cached deps
|
||||||
if: ${{ !(runner.os == 'macOS' && inputs.macos-combine-only) }}
|
if: ${{ !(runner.os == 'macOS' && inputs.macos-combine-only) }}
|
||||||
uses: actions/cache@v5
|
uses: actions/cache@v6
|
||||||
with:
|
with:
|
||||||
path: ${{ inputs.cache-path }}
|
path: ${{ inputs.cache-path }}
|
||||||
key: ${{ inputs.cache-key }}
|
key: ${{ inputs.cache-key }}
|
||||||
|
|||||||
2
.github/workflows/check_locale.yml
vendored
2
.github/workflows/check_locale.yml
vendored
@@ -14,7 +14,7 @@ jobs:
|
|||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout repository
|
- name: Checkout repository
|
||||||
uses: actions/checkout@v6
|
uses: actions/checkout@v7
|
||||||
|
|
||||||
- name: Install gettext
|
- name: Install gettext
|
||||||
run: |
|
run: |
|
||||||
|
|||||||
102
.github/workflows/check_profiles.yml
vendored
102
.github/workflows/check_profiles.yml
vendored
@@ -24,7 +24,7 @@ jobs:
|
|||||||
runs-on: ubuntu-24.04
|
runs-on: ubuntu-24.04
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout repository
|
- name: Checkout repository
|
||||||
uses: actions/checkout@v6
|
uses: actions/checkout@v7
|
||||||
|
|
||||||
- name: Run extra JSON check
|
- name: Run extra JSON check
|
||||||
id: extra_json_check
|
id: extra_json_check
|
||||||
@@ -77,11 +77,101 @@ jobs:
|
|||||||
continue-on-error: true
|
continue-on-error: true
|
||||||
working-directory: ${{ github.workspace }}
|
working-directory: ${{ github.workspace }}
|
||||||
run: |
|
run: |
|
||||||
set +e
|
fixtures_dir="${{ runner.temp }}/profile-fixtures"
|
||||||
curl -LJO https://github.com/OrcaSlicer/OrcaSlicer/releases/download/nightly-builds/orca_custom_preset_tests.zip
|
output_dir="${{ runner.temp }}/custom-preset-validation"
|
||||||
unzip -q ./orca_custom_preset_tests.zip -d ${{ github.workspace }}/resources/profiles
|
combined_log="${{ runner.temp }}/validate_custom.log"
|
||||||
./OrcaSlicer_profile_validator -p ${{ github.workspace }}/resources/profiles -l 2 2>&1 | tee ${{ runner.temp }}/validate_custom.log
|
summary="${output_dir}/summary.md"
|
||||||
exit ${PIPESTATUS[0]}
|
release_url="https://github.com/OrcaSlicer/OrcaSlicer-profile-validator/releases/download/fixture-archive"
|
||||||
|
|
||||||
|
rm -rf "${fixtures_dir}" "${output_dir}"
|
||||||
|
mkdir -p "${fixtures_dir}" "${output_dir}"
|
||||||
|
|
||||||
|
curl -fsSL -o "${fixtures_dir}/manifest.json" "${release_url}/manifest.json"
|
||||||
|
|
||||||
|
MANIFEST_PATH="${fixtures_dir}/manifest.json" python3 <<'PY' > "${fixtures_dir}/fixtures.tsv"
|
||||||
|
import json
|
||||||
|
import os
|
||||||
|
|
||||||
|
with open(os.environ["MANIFEST_PATH"], encoding="utf-8") as fh:
|
||||||
|
manifest = json.load(fh)
|
||||||
|
|
||||||
|
if isinstance(manifest, dict):
|
||||||
|
entries = manifest.get("fixtures", [])
|
||||||
|
else:
|
||||||
|
entries = manifest
|
||||||
|
|
||||||
|
for entry in entries:
|
||||||
|
version = entry.get("version", "")
|
||||||
|
asset = entry.get("asset", "")
|
||||||
|
sha256 = entry.get("asset_sha256", "")
|
||||||
|
if not version or not asset:
|
||||||
|
continue
|
||||||
|
print(f"{version}\t{asset}\t{sha256}")
|
||||||
|
PY
|
||||||
|
|
||||||
|
if [ ! -s "${fixtures_dir}/fixtures.tsv" ]; then
|
||||||
|
echo "No custom preset fixtures found in ${release_url}/manifest.json" | tee "${combined_log}"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
{
|
||||||
|
echo "## Custom Preset Fixture Validation"
|
||||||
|
echo ""
|
||||||
|
echo "| Version | Status | Log |"
|
||||||
|
echo "| --- | --- | --- |"
|
||||||
|
} > "${summary}"
|
||||||
|
|
||||||
|
status=0
|
||||||
|
failed_logs=()
|
||||||
|
|
||||||
|
while IFS=$'\t' read -r version asset expected_sha256; do
|
||||||
|
fixture_zip="${fixtures_dir}/${asset}"
|
||||||
|
asset_url_name="$(python3 -c 'import sys, urllib.parse; print(urllib.parse.quote(sys.argv[1], safe=""))' "${asset}")"
|
||||||
|
profile_tree="${output_dir}/profiles-${version}"
|
||||||
|
log_path="${output_dir}/${version}.log"
|
||||||
|
|
||||||
|
curl -fsSL -o "${fixture_zip}" "${release_url}/${asset_url_name}"
|
||||||
|
|
||||||
|
if [ -n "${expected_sha256}" ] && [ "${expected_sha256}" != "<sha256>" ]; then
|
||||||
|
echo "${expected_sha256} ${fixture_zip}" | sha256sum -c -
|
||||||
|
fi
|
||||||
|
|
||||||
|
rm -rf "${profile_tree}"
|
||||||
|
mkdir -p "${profile_tree}"
|
||||||
|
cp -a "${{ github.workspace }}/resources/profiles/." "${profile_tree}/"
|
||||||
|
rm -rf "${profile_tree}/user"
|
||||||
|
unzip -q "${fixture_zip}" -d "${profile_tree}"
|
||||||
|
|
||||||
|
set +e
|
||||||
|
./OrcaSlicer_profile_validator -p "${profile_tree}" -l 2 > "${log_path}" 2>&1
|
||||||
|
result=$?
|
||||||
|
set -e
|
||||||
|
|
||||||
|
if [ "${result}" -eq 0 ]; then
|
||||||
|
echo "| ${version} | PASS | ${version}.log |" >> "${summary}"
|
||||||
|
else
|
||||||
|
echo "| ${version} | FAIL | ${version}.log |" >> "${summary}"
|
||||||
|
failed_logs+=("${log_path}")
|
||||||
|
status=1
|
||||||
|
fi
|
||||||
|
done < "${fixtures_dir}/fixtures.tsv"
|
||||||
|
|
||||||
|
{
|
||||||
|
cat "${summary}"
|
||||||
|
if [ "${#failed_logs[@]}" -gt 0 ]; then
|
||||||
|
echo ""
|
||||||
|
echo "## Failed Fixture Logs"
|
||||||
|
for log_path in "${failed_logs[@]}"; do
|
||||||
|
echo ""
|
||||||
|
echo "### $(basename "${log_path}" .log)"
|
||||||
|
echo '```'
|
||||||
|
head -c 12000 "${log_path}" || echo "No output captured"
|
||||||
|
echo '```'
|
||||||
|
done
|
||||||
|
fi
|
||||||
|
} | tee "${combined_log}"
|
||||||
|
|
||||||
|
exit "${status}"
|
||||||
|
|
||||||
- name: Prepare PR number for comment workflow
|
- name: Prepare PR number for comment workflow
|
||||||
if: ${{ always() && github.event_name == 'pull_request' }}
|
if: ${{ always() && github.event_name == 'pull_request' }}
|
||||||
|
|||||||
2
.github/workflows/dedupe-issues.yml
vendored
2
.github/workflows/dedupe-issues.yml
vendored
@@ -20,7 +20,7 @@ jobs:
|
|||||||
|
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout repository
|
- name: Checkout repository
|
||||||
uses: actions/checkout@v6
|
uses: actions/checkout@v7
|
||||||
|
|
||||||
- name: Run Claude Code slash command
|
- name: Run Claude Code slash command
|
||||||
uses: anthropics/claude-code-base-action@beta
|
uses: anthropics/claude-code-base-action@beta
|
||||||
|
|||||||
2
.github/workflows/doxygen-docs.yml
vendored
2
.github/workflows/doxygen-docs.yml
vendored
@@ -26,7 +26,7 @@ jobs:
|
|||||||
remove-existing-swap-files: true
|
remove-existing-swap-files: true
|
||||||
|
|
||||||
- name: Checkout repository
|
- name: Checkout repository
|
||||||
uses: actions/checkout@v6
|
uses: actions/checkout@v7
|
||||||
|
|
||||||
- name: Install Doxygen and Graphviz
|
- name: Install Doxygen and Graphviz
|
||||||
run: |
|
run: |
|
||||||
|
|||||||
4
.github/workflows/shellcheck.yml
vendored
4
.github/workflows/shellcheck.yml
vendored
@@ -21,7 +21,7 @@ jobs:
|
|||||||
steps:
|
steps:
|
||||||
- name: Cache shellcheck download
|
- name: Cache shellcheck download
|
||||||
id: cache-shellcheck-v0_11
|
id: cache-shellcheck-v0_11
|
||||||
uses: actions/cache@v5
|
uses: actions/cache@v6
|
||||||
with:
|
with:
|
||||||
path: ~/shellcheck
|
path: ~/shellcheck
|
||||||
key: ${{ runner.os }}-shellcheck-v0_11
|
key: ${{ runner.os }}-shellcheck-v0_11
|
||||||
@@ -36,7 +36,7 @@ jobs:
|
|||||||
tar -xvf ~/sc.tar.xz -C ~
|
tar -xvf ~/sc.tar.xz -C ~
|
||||||
mv ~/shellcheck-"${INPUT_VERSION}"/shellcheck ~/shellcheck
|
mv ~/shellcheck-"${INPUT_VERSION}"/shellcheck ~/shellcheck
|
||||||
|
|
||||||
- uses: actions/checkout@v6
|
- uses: actions/checkout@v7
|
||||||
with:
|
with:
|
||||||
fetch-depth: 1
|
fetch-depth: 1
|
||||||
|
|
||||||
|
|||||||
2
.github/workflows/update-translation.yml
vendored
2
.github/workflows/update-translation.yml
vendored
@@ -10,7 +10,7 @@ jobs:
|
|||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout repository
|
- name: Checkout repository
|
||||||
uses: actions/checkout@v6
|
uses: actions/checkout@v7
|
||||||
|
|
||||||
- name: Setup Python
|
- name: Setup Python
|
||||||
uses: actions/setup-python@v6
|
uses: actions/setup-python@v6
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -1,6 +1,7 @@
|
|||||||
{
|
{
|
||||||
"type": "process",
|
"type": "process",
|
||||||
"name": "0.20mm Optimal 0.6 nozzle @Anker",
|
"name": "0.20mm Optimal 0.6 nozzle @Anker",
|
||||||
|
"renamed_from": "0.20mm Optimal 0.6 nozzle @Anker.json",
|
||||||
"inherits": "fdm_process_anker_common_0_6",
|
"inherits": "fdm_process_anker_common_0_6",
|
||||||
"from": "system",
|
"from": "system",
|
||||||
"setting_id": "re5qmcOFJ1OJP3Ip",
|
"setting_id": "re5qmcOFJ1OJP3Ip",
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
{
|
{
|
||||||
"type": "filament",
|
"type": "filament",
|
||||||
"name": "Bambu PLA Tough @BBL X1C",
|
"name": "Bambu PLA Tough @BBL X1C",
|
||||||
|
"renamed_from": "Bambu PLA Impact @BBL X1C",
|
||||||
"inherits": "Bambu PLA Tough @base",
|
"inherits": "Bambu PLA Tough @base",
|
||||||
"from": "system",
|
"from": "system",
|
||||||
"setting_id": "GFSA09_02",
|
"setting_id": "GFSA09_02",
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
{
|
{
|
||||||
"type": "filament",
|
"type": "filament",
|
||||||
"name": "Panchroma PLA Satin @BBL A1",
|
"name": "Panchroma PLA Satin @BBL A1",
|
||||||
|
"renamed_from": "Panchroma PLA Stain @BBL A1",
|
||||||
"inherits": "Panchroma PLA Satin @base",
|
"inherits": "Panchroma PLA Satin @base",
|
||||||
"from": "system",
|
"from": "system",
|
||||||
"setting_id": "GFSPM005_00",
|
"setting_id": "GFSPM005_00",
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
{
|
{
|
||||||
"type": "filament",
|
"type": "filament",
|
||||||
"name": "Panchroma PLA Satin @BBL A1M",
|
"name": "Panchroma PLA Satin @BBL A1M",
|
||||||
|
"renamed_from": "Panchroma PLA Stain @BBL A1M",
|
||||||
"inherits": "Panchroma PLA Satin @base",
|
"inherits": "Panchroma PLA Satin @base",
|
||||||
"from": "system",
|
"from": "system",
|
||||||
"setting_id": "GFSPM005_02",
|
"setting_id": "GFSPM005_02",
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
{
|
{
|
||||||
"type": "filament",
|
"type": "filament",
|
||||||
"name": "Panchroma PLA Satin @BBL P1P",
|
"name": "Panchroma PLA Satin @BBL P1P",
|
||||||
|
"renamed_from": "Panchroma PLA Stain @BBL P1P",
|
||||||
"inherits": "Panchroma PLA Satin @base",
|
"inherits": "Panchroma PLA Satin @base",
|
||||||
"from": "system",
|
"from": "system",
|
||||||
"setting_id": "GFSPM005_04",
|
"setting_id": "GFSPM005_04",
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
{
|
{
|
||||||
"type": "filament",
|
"type": "filament",
|
||||||
"name": "Panchroma PLA Satin @BBL X1",
|
"name": "Panchroma PLA Satin @BBL X1",
|
||||||
|
"renamed_from": "Panchroma PLA Stain @BBL X1",
|
||||||
"inherits": "Panchroma PLA Satin @base",
|
"inherits": "Panchroma PLA Satin @base",
|
||||||
"from": "system",
|
"from": "system",
|
||||||
"setting_id": "GFSPM005_06",
|
"setting_id": "GFSPM005_06",
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
{
|
{
|
||||||
"type": "process",
|
"type": "process",
|
||||||
"name": "0.20mm Standard @BBL X1C",
|
"name": "0.20mm Standard @BBL X1C",
|
||||||
|
"renamed_from": "0.20mm Bambu Support W @BBL X1C",
|
||||||
"inherits": "fdm_process_single_0.20",
|
"inherits": "fdm_process_single_0.20",
|
||||||
"from": "system",
|
"from": "system",
|
||||||
"setting_id": "GP004",
|
"setting_id": "GP004",
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
{
|
{
|
||||||
"type": "process",
|
"type": "process",
|
||||||
"name": "0.12mm Fine @Creality Ender3V3SE 0.4",
|
"name": "0.12mm Fine @Creality Ender3V3SE 0.4",
|
||||||
|
"renamed_from": "0.12mm Fine @Creality Ender3V3SE",
|
||||||
"inherits": "fdm_process_creality_common",
|
"inherits": "fdm_process_creality_common",
|
||||||
"from": "system",
|
"from": "system",
|
||||||
"setting_id": "W68mSPdmat2rCXuD",
|
"setting_id": "W68mSPdmat2rCXuD",
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
{
|
{
|
||||||
"type": "process",
|
"type": "process",
|
||||||
"name": "0.16mm Optimal @Creality Ender3V3SE 0.4",
|
"name": "0.16mm Optimal @Creality Ender3V3SE 0.4",
|
||||||
|
"renamed_from": "0.16mm Optimal @Creality Ender3V3SE",
|
||||||
"inherits": "fdm_process_creality_common",
|
"inherits": "fdm_process_creality_common",
|
||||||
"from": "system",
|
"from": "system",
|
||||||
"setting_id": "jvnrh3jh6Btbs1Ja",
|
"setting_id": "jvnrh3jh6Btbs1Ja",
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
{
|
{
|
||||||
"type": "process",
|
"type": "process",
|
||||||
"name": "0.20mm Standard @Creality Ender3V3SE 0.4",
|
"name": "0.20mm Standard @Creality Ender3V3SE 0.4",
|
||||||
|
"renamed_from": "0.20mm Standard @Creality Ender3V3SE",
|
||||||
"inherits": "fdm_process_creality_common",
|
"inherits": "fdm_process_creality_common",
|
||||||
"from": "system",
|
"from": "system",
|
||||||
"setting_id": "YLkw9eyyK7cm97ek",
|
"setting_id": "YLkw9eyyK7cm97ek",
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
{
|
{
|
||||||
"type": "process",
|
"type": "process",
|
||||||
"name": "0.20mm Standard @Creality K1 SE",
|
"name": "0.20mm Standard @Creality K1 SE",
|
||||||
|
"renamed_from": "0.20mm Fast @Creality K1 SE 0.4",
|
||||||
"inherits": "fdm_process_creality_common",
|
"inherits": "fdm_process_creality_common",
|
||||||
"from": "system",
|
"from": "system",
|
||||||
"setting_id": "eR9pRC1qPENNx8U9",
|
"setting_id": "eR9pRC1qPENNx8U9",
|
||||||
@@ -264,4 +265,4 @@
|
|||||||
"wipe_tower_extra_spacing": "100%",
|
"wipe_tower_extra_spacing": "100%",
|
||||||
"wipe_tower_rotation_angle": "0",
|
"wipe_tower_rotation_angle": "0",
|
||||||
"wiping_volumes_extruders": "70,70,70,70,70,70,70,70,70,70"
|
"wiping_volumes_extruders": "70,70,70,70,70,70,70,70,70,70"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
{
|
{
|
||||||
"type": "process",
|
"type": "process",
|
||||||
"name": "0.24mm Draft @Creality Ender3V3SE 0.4",
|
"name": "0.24mm Draft @Creality Ender3V3SE 0.4",
|
||||||
|
"renamed_from": "0.24mm Draft @Creality Ender3V3SE",
|
||||||
"inherits": "fdm_process_creality_common",
|
"inherits": "fdm_process_creality_common",
|
||||||
"from": "system",
|
"from": "system",
|
||||||
"setting_id": "Hg10EUNCLMEYYBN1",
|
"setting_id": "Hg10EUNCLMEYYBN1",
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
{
|
{
|
||||||
"type": "process",
|
"type": "process",
|
||||||
"name": "0.48mm Draft @Creality K1C",
|
"name": "0.48mm Draft @Creality K1C",
|
||||||
|
"renamed_from": "0.48mm Draft @Creality K1C (0.8 nozzle)",
|
||||||
"inherits": "fdm_process_common_klipper",
|
"inherits": "fdm_process_common_klipper",
|
||||||
"from": "system",
|
"from": "system",
|
||||||
"setting_id": "qaiff3f8gSQ1GVj1",
|
"setting_id": "qaiff3f8gSQ1GVj1",
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
"type": "filament",
|
"type": "filament",
|
||||||
"setting_id": "pKzSR8XeyyUDbrNW",
|
"setting_id": "pKzSR8XeyyUDbrNW",
|
||||||
"name": "Generic PETG PRO @Elegoo",
|
"name": "Generic PETG PRO @Elegoo",
|
||||||
|
"renamed_from": "Elegoo Generic PETG PRO",
|
||||||
"from": "system",
|
"from": "system",
|
||||||
"instantiation": "true",
|
"instantiation": "true",
|
||||||
"inherits": "Generic PETG @base",
|
"inherits": "Generic PETG @base",
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
{
|
{
|
||||||
"type": "filament",
|
"type": "filament",
|
||||||
"name": "Ginger Generic PETG",
|
"name": "Ginger Generic PETG",
|
||||||
|
"renamed_from": "Ginger Generic rPETG",
|
||||||
"inherits": "fdm_filament_common",
|
"inherits": "fdm_filament_common",
|
||||||
"from": "system",
|
"from": "system",
|
||||||
"setting_id": "ue95N2e65rdp5K6c",
|
"setting_id": "ue95N2e65rdp5K6c",
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
{
|
{
|
||||||
"type": "filament",
|
"type": "filament",
|
||||||
"name": "Ginger Generic PLA",
|
"name": "Ginger Generic PLA",
|
||||||
|
"renamed_from": "Ginger Generic rPLA",
|
||||||
"inherits": "fdm_filament_common",
|
"inherits": "fdm_filament_common",
|
||||||
"from": "system",
|
"from": "system",
|
||||||
"setting_id": "Z1scjKDBFoDaTa2C",
|
"setting_id": "Z1scjKDBFoDaTa2C",
|
||||||
|
|||||||
@@ -18,5 +18,5 @@
|
|||||||
"5"
|
"5"
|
||||||
],
|
],
|
||||||
"compatible_printers": [],
|
"compatible_printers": [],
|
||||||
"renamed_from": "Elegoo PETG PRO"
|
"renamed_from": "Elegoo PETG PRO;Elegoo PETG Pro @System"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -33,5 +33,5 @@
|
|||||||
"250"
|
"250"
|
||||||
],
|
],
|
||||||
"compatible_printers": [],
|
"compatible_printers": [],
|
||||||
"renamed_from": "Elegoo Rapid PETG;Elegoo Rapid PETG+"
|
"renamed_from": "Elegoo Rapid PETG;Elegoo Rapid PETG+;Elegoo RAPID PETG;Elegoo RAPID PETG+"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -45,5 +45,5 @@
|
|||||||
"; filament start gcode\n{if (bed_temperature[current_extruder] >55)||(bed_temperature_initial_layer[current_extruder] >55)}M106 P3 S200\n{elsif(bed_temperature[current_extruder] >50)||(bed_temperature_initial_layer[current_extruder] >50)}M106 P3 S150\n{elsif(bed_temperature[current_extruder] >45)||(bed_temperature_initial_layer[current_extruder] >45)}M106 P3 S50\n{endif}\n\n{if activate_air_filtration[current_extruder] && support_air_filtration}\nM106 P3 S{during_print_exhaust_fan_speed_num[current_extruder]} \n{endif}"
|
"; filament start gcode\n{if (bed_temperature[current_extruder] >55)||(bed_temperature_initial_layer[current_extruder] >55)}M106 P3 S200\n{elsif(bed_temperature[current_extruder] >50)||(bed_temperature_initial_layer[current_extruder] >50)}M106 P3 S150\n{elsif(bed_temperature[current_extruder] >45)||(bed_temperature_initial_layer[current_extruder] >45)}M106 P3 S50\n{endif}\n\n{if activate_air_filtration[current_extruder] && support_air_filtration}\nM106 P3 S{during_print_exhaust_fan_speed_num[current_extruder]} \n{endif}"
|
||||||
],
|
],
|
||||||
"compatible_printers": [],
|
"compatible_printers": [],
|
||||||
"renamed_from": "Elegoo Rapid PLA+"
|
"renamed_from": "Elegoo Rapid PLA+;Elegoo RAPID PLA+"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
{
|
{
|
||||||
"type": "filament",
|
"type": "filament",
|
||||||
"name": "Peopoly Generic PLA",
|
"name": "Peopoly Generic PLA",
|
||||||
|
"renamed_from": "Peopoly Generic PLA 0.8 nozzle",
|
||||||
"inherits": "fdm_filament_pla",
|
"inherits": "fdm_filament_pla",
|
||||||
"from": "system",
|
"from": "system",
|
||||||
"setting_id": "KNsVV4dvEWAAkzDE",
|
"setting_id": "KNsVV4dvEWAAkzDE",
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
{
|
{
|
||||||
"type": "filament",
|
"type": "filament",
|
||||||
"name": "Snapmaker PLA",
|
"name": "Snapmaker PLA",
|
||||||
|
"renamed_from": "PolyLite PLA",
|
||||||
"inherits": "Snapmaker PLA @base",
|
"inherits": "Snapmaker PLA @base",
|
||||||
"from": "system",
|
"from": "system",
|
||||||
"setting_id": "cW1b4nGxE9yXIXJP",
|
"setting_id": "cW1b4nGxE9yXIXJP",
|
||||||
|
|||||||
@@ -206,6 +206,10 @@
|
|||||||
"name": "0.24mm Fine 0.8 nozzle @Voron",
|
"name": "0.24mm Fine 0.8 nozzle @Voron",
|
||||||
"sub_path": "process/0.24mm Fine 0.8 nozzle @Voron.json"
|
"sub_path": "process/0.24mm Fine 0.8 nozzle @Voron.json"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"name": "0.32mm Optimal 0.8 nozzle @Voron",
|
||||||
|
"sub_path": "process/0.32mm Optimal 0.8 nozzle @Voron.json"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"name": "0.40mm Standard 0.8 nozzle @Voron",
|
"name": "0.40mm Standard 0.8 nozzle @Voron",
|
||||||
"sub_path": "process/0.40mm Standard 0.8 nozzle @Voron.json"
|
"sub_path": "process/0.40mm Standard 0.8 nozzle @Voron.json"
|
||||||
|
|||||||
@@ -0,0 +1,11 @@
|
|||||||
|
{
|
||||||
|
"type": "process",
|
||||||
|
"name": "0.32mm Optimal 0.8 nozzle @Voron",
|
||||||
|
"inherits": "fdm_process_voron_common_0_8",
|
||||||
|
"from": "system",
|
||||||
|
"setting_id": "ivS6U4AuIoj1cJhZ",
|
||||||
|
"instantiation": "true",
|
||||||
|
"bottom_shell_layers": "3",
|
||||||
|
"top_shell_layers": "3",
|
||||||
|
"layer_height": "0.32"
|
||||||
|
}
|
||||||
@@ -201,9 +201,12 @@ if (WIN32)
|
|||||||
if(MSVC)
|
if(MSVC)
|
||||||
target_link_options(OrcaSlicer_app_gui PUBLIC "$<$<CONFIG:RELEASE>:/DEBUG>")
|
target_link_options(OrcaSlicer_app_gui PUBLIC "$<$<CONFIG:RELEASE>:/DEBUG>")
|
||||||
endif()
|
endif()
|
||||||
target_compile_definitions(OrcaSlicer_app_gui PRIVATE -DSLIC3R_WRAPPER_NOCONSOLE)
|
target_compile_definitions(OrcaSlicer_app_gui PRIVATE "$<$<NOT:$<CONFIG:RelWithDebInfo>>:SLIC3R_WRAPPER_NOCONSOLE>")
|
||||||
add_dependencies(OrcaSlicer_app_gui OrcaSlicer)
|
add_dependencies(OrcaSlicer_app_gui OrcaSlicer)
|
||||||
set_target_properties(OrcaSlicer_app_gui PROPERTIES OUTPUT_NAME "orca-slicer")
|
set_target_properties(OrcaSlicer_app_gui PROPERTIES
|
||||||
|
OUTPUT_NAME "orca-slicer"
|
||||||
|
WIN32_EXECUTABLE "$<NOT:$<CONFIG:RelWithDebInfo>>"
|
||||||
|
)
|
||||||
target_link_libraries(OrcaSlicer_app_gui PRIVATE boost_headeronly)
|
target_link_libraries(OrcaSlicer_app_gui PRIVATE boost_headeronly)
|
||||||
endif ()
|
endif ()
|
||||||
|
|
||||||
|
|||||||
@@ -532,6 +532,7 @@ endif ()
|
|||||||
encoding_check(libslic3r)
|
encoding_check(libslic3r)
|
||||||
|
|
||||||
target_compile_definitions(libslic3r PUBLIC -DUSE_TBB -DTBB_USE_CAPTURED_EXCEPTION=0)
|
target_compile_definitions(libslic3r PUBLIC -DUSE_TBB -DTBB_USE_CAPTURED_EXCEPTION=0)
|
||||||
|
target_compile_definitions(libslic3r PRIVATE $<$<CONFIG:RelWithDebInfo>:SLIC3R_CONSOLE_LOG>)
|
||||||
target_include_directories(libslic3r PRIVATE ${CMAKE_CURRENT_SOURCE_DIR} PUBLIC ${CMAKE_CURRENT_BINARY_DIR})
|
target_include_directories(libslic3r PRIVATE ${CMAKE_CURRENT_SOURCE_DIR} PUBLIC ${CMAKE_CURRENT_BINARY_DIR})
|
||||||
target_include_directories(libslic3r SYSTEM PUBLIC ${EXPAT_INCLUDE_DIRS})
|
target_include_directories(libslic3r SYSTEM PUBLIC ${EXPAT_INCLUDE_DIRS})
|
||||||
|
|
||||||
|
|||||||
@@ -836,9 +836,11 @@ namespace client
|
|||||||
static std::map<std::string, std::string> tag_to_error_message;
|
static std::map<std::string, std::string> tag_to_error_message;
|
||||||
|
|
||||||
size_t get_extruder_id() const {
|
size_t get_extruder_id() const {
|
||||||
const ConfigOptionInts * filament_map_opt = external_config->option<ConfigOptionInts>("filament_map");
|
if (external_config != nullptr) {
|
||||||
if (filament_map_opt && current_extruder_id < filament_map_opt->values.size()) {
|
const ConfigOptionInts * filament_map_opt = external_config->option<ConfigOptionInts>("filament_map");
|
||||||
return filament_map_opt->values[current_extruder_id];
|
if (filament_map_opt && current_extruder_id < filament_map_opt->values.size()) {
|
||||||
|
return filament_map_opt->values[current_extruder_id];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -1096,27 +1098,109 @@ namespace client
|
|||||||
const ConfigOptionVectorBase* vec = static_cast<const ConfigOptionVectorBase*>(opt.opt);
|
const ConfigOptionVectorBase* vec = static_cast<const ConfigOptionVectorBase*>(opt.opt);
|
||||||
if (vec->empty())
|
if (vec->empty())
|
||||||
ctx->throw_exception("Indexing an empty vector variable", opt.it_range);
|
ctx->throw_exception("Indexing an empty vector variable", opt.it_range);
|
||||||
|
|
||||||
|
// Helper to resolve a FloatOrPercent value (handles ratio_over chain for percent values).
|
||||||
|
// elem_index: the element index used to access this vector element, so that
|
||||||
|
// parent vectors (via ratio_over) use the same index rather than the current extruder.
|
||||||
|
auto resolve_float_or_percent = [ctx, &opt, &output](const FloatOrPercent &fop, size_t elem_index) {
|
||||||
|
std::string opt_key(opt.it_range.begin(), opt.it_range.end());
|
||||||
|
if (boost::ends_with(opt_key, "line_width")) {
|
||||||
|
// Line width supports defaults and a complex graph of dependencies.
|
||||||
|
output.set_d(Flow::extrusion_width(opt_key, *ctx, static_cast<unsigned int>(ctx->current_extruder_id)));
|
||||||
|
} else if (! fop.percent) {
|
||||||
|
// Not a percent, just return the value.
|
||||||
|
output.set_d(fop.value);
|
||||||
|
} else {
|
||||||
|
// Resolve dependencies using the "ratio_over" link to a parent value.
|
||||||
|
const ConfigOptionDef *opt_def = print_config_def.get(opt_key);
|
||||||
|
assert(opt_def != nullptr);
|
||||||
|
double v = fop.value * 0.01; // percent to ratio
|
||||||
|
for (;;) {
|
||||||
|
const ConfigOption *opt_parent = opt_def->ratio_over.empty() ? nullptr : ctx->resolve_symbol(opt_def->ratio_over);
|
||||||
|
if (opt_parent == nullptr)
|
||||||
|
ctx->throw_exception("FloatOrPercent variable failed to resolve the \"ratio_over\" dependencies", opt.it_range);
|
||||||
|
if (boost::ends_with(opt_def->ratio_over, "line_width")) {
|
||||||
|
// Line width supports defaults and a complex graph of dependencies.
|
||||||
|
assert(opt_parent->type() == coFloatOrPercent);
|
||||||
|
v *= Flow::extrusion_width(opt_def->ratio_over, static_cast<const ConfigOptionFloatOrPercent*>(opt_parent), *ctx, static_cast<unsigned int>(ctx->current_extruder_id));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (opt_parent->type() == coFloat || opt_parent->type() == coFloatOrPercent) {
|
||||||
|
v *= opt_parent->getFloat();
|
||||||
|
if (opt_parent->type() == coFloat || ! static_cast<const ConfigOptionFloatOrPercent*>(opt_parent)->percent)
|
||||||
|
break;
|
||||||
|
v *= 0.01; // percent to ratio
|
||||||
|
} else if (opt_parent->type() == coFloats) {
|
||||||
|
// Vector parent: extract the value for the current extruder.
|
||||||
|
const ConfigOptionFloatsNullable *parent_nullable = dynamic_cast<const ConfigOptionFloatsNullable *>(opt_parent);
|
||||||
|
if (parent_nullable) {
|
||||||
|
v *= (parent_nullable->size() == 1) ? parent_nullable->get_at(0) : parent_nullable->get_at(elem_index);
|
||||||
|
} else {
|
||||||
|
const ConfigOptionFloats *parent_vec = static_cast<const ConfigOptionFloats *>(opt_parent);
|
||||||
|
v *= (parent_vec->size() == 1) ? parent_vec->get_at(0) : parent_vec->get_at(elem_index);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
} else if (opt_parent->type() == coFloatsOrPercents) {
|
||||||
|
// Vector parent with percent support: extract the FloatOrPercent for the current extruder.
|
||||||
|
const ConfigOptionFloatsOrPercentsNullable *parent_nullable = dynamic_cast<const ConfigOptionFloatsOrPercentsNullable *>(opt_parent);
|
||||||
|
if (parent_nullable) {
|
||||||
|
const FloatOrPercent &parent_fop = (parent_nullable->size() == 1) ? parent_nullable->get_at(0) : parent_nullable->get_at(elem_index);
|
||||||
|
if (! parent_fop.percent) {
|
||||||
|
v *= parent_fop.value;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
v *= parent_fop.value * 0.01; // percent to ratio
|
||||||
|
} else {
|
||||||
|
const ConfigOptionFloatsOrPercents *parent_vec = static_cast<const ConfigOptionFloatsOrPercents *>(opt_parent);
|
||||||
|
const FloatOrPercent &parent_fop = (parent_vec->size() == 1) ? parent_vec->get_at(0) : parent_vec->get_at(elem_index);
|
||||||
|
if (! parent_fop.percent) {
|
||||||
|
v *= parent_fop.value;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
v *= parent_fop.value * 0.01; // percent to ratio
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Continue one level up in the "ratio_over" hierarchy.
|
||||||
|
opt_def = print_config_def.get(opt_def->ratio_over);
|
||||||
|
assert(opt_def != nullptr);
|
||||||
|
}
|
||||||
|
output.set_d(v);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
if (!opt.has_index()) {
|
if (!opt.has_index()) {
|
||||||
// Allow omitting extruder id when referencing vectors
|
// Allow omitting extruder id when referencing vectors
|
||||||
switch (opt.opt->type()) {
|
switch (opt.opt->type()) {
|
||||||
case coFloats: {
|
case coFloats: {
|
||||||
const ConfigOptionFloatsNullable* opt_floatsnullable = static_cast<const ConfigOptionFloatsNullable *>(opt.opt);
|
const ConfigOptionFloatsNullable* opt_floatsnullable = dynamic_cast<const ConfigOptionFloatsNullable *>(opt.opt);
|
||||||
if (opt_floatsnullable) {
|
if (opt_floatsnullable) {
|
||||||
if (opt_floatsnullable->size() == 1) { // old version
|
if (opt_floatsnullable->size() == 1) { // old version
|
||||||
output.set_d(static_cast<const ConfigOptionFloatsNullable*>(opt.opt)->get_at(0));
|
output.set_d(opt_floatsnullable->get_at(0));
|
||||||
} else {
|
} else {
|
||||||
output.set_d(static_cast<const ConfigOptionFloatsNullable*>(opt.opt)->get_at(ctx->get_extruder_id()));
|
output.set_d(opt_floatsnullable->get_at(ctx->get_extruder_id()));
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
const ConfigOptionFloats* opt_floats = static_cast<const ConfigOptionFloats*>(opt.opt);
|
const ConfigOptionFloats* opt_floats = static_cast<const ConfigOptionFloats*>(opt.opt);
|
||||||
if (opt_floats->size() == 1) { // old version
|
if (opt_floats->size() == 1) { // old version
|
||||||
output.set_d(static_cast<const ConfigOptionFloats*>(opt.opt)->get_at(0));
|
output.set_d(opt_floats->get_at(0));
|
||||||
} else {
|
} else {
|
||||||
output.set_d(static_cast<const ConfigOptionFloats*>(opt.opt)->get_at(ctx->get_extruder_id()));
|
output.set_d(opt_floats->get_at(ctx->get_extruder_id()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case coFloatsOrPercents: {
|
||||||
|
const ConfigOptionFloatsOrPercentsNullable *opt_vec_nullable = dynamic_cast<const ConfigOptionFloatsOrPercentsNullable *>(opt.opt);
|
||||||
|
if (opt_vec_nullable) {
|
||||||
|
size_t elem_index = (opt_vec_nullable->size() == 1) ? 0 : ctx->get_extruder_id();
|
||||||
|
resolve_float_or_percent(opt_vec_nullable->get_at(elem_index), elem_index);
|
||||||
|
} else {
|
||||||
|
const ConfigOptionFloatsOrPercents *opt_vec = static_cast<const ConfigOptionFloatsOrPercents *>(opt.opt);
|
||||||
|
size_t elem_index = (opt_vec->size() == 1) ? 0 : ctx->get_extruder_id();
|
||||||
|
resolve_float_or_percent(opt_vec->get_at(elem_index), elem_index);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
default: ctx->throw_exception("Referencing a vector variable when scalar is expected", opt.it_range);
|
default: ctx->throw_exception("Referencing a vector variable when scalar is expected", opt.it_range);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@@ -1131,6 +1215,15 @@ namespace client
|
|||||||
case coPoints: output.set_s(to_string(static_cast<const ConfigOptionPoints*>(opt.opt)->values[idx])); break;
|
case coPoints: output.set_s(to_string(static_cast<const ConfigOptionPoints*>(opt.opt)->values[idx])); break;
|
||||||
case coBools: output.set_b(static_cast<const ConfigOptionBools*>(opt.opt)->values[idx] != 0); break;
|
case coBools: output.set_b(static_cast<const ConfigOptionBools*>(opt.opt)->values[idx] != 0); break;
|
||||||
case coEnums: output.set_i(static_cast<const ConfigOptionInts *>(opt.opt)->values[idx]); break;
|
case coEnums: output.set_i(static_cast<const ConfigOptionInts *>(opt.opt)->values[idx]); break;
|
||||||
|
case coFloatsOrPercents: {
|
||||||
|
const ConfigOptionFloatsOrPercentsNullable *opt_vec_nullable = dynamic_cast<const ConfigOptionFloatsOrPercentsNullable *>(opt.opt);
|
||||||
|
if (opt_vec_nullable) {
|
||||||
|
resolve_float_or_percent(opt_vec_nullable->values[idx], idx);
|
||||||
|
} else {
|
||||||
|
resolve_float_or_percent(static_cast<const ConfigOptionFloatsOrPercents *>(opt.opt)->values[idx], idx);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
default:
|
default:
|
||||||
ctx->throw_exception("Unsupported vector variable type", opt.it_range);
|
ctx->throw_exception("Unsupported vector variable type", opt.it_range);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -21,11 +21,12 @@ void PrintTryCancel::operator()()
|
|||||||
|
|
||||||
size_t PrintStateBase::g_last_timestamp = 0;
|
size_t PrintStateBase::g_last_timestamp = 0;
|
||||||
|
|
||||||
// Update "scale", "input_filename", "input_filename_base" placeholders from the current m_objects.
|
// Update "scale", "input_filename", "input_filename_base", "first_object_name" placeholders from the current m_objects.
|
||||||
void PrintBase::update_object_placeholders(DynamicConfig &config, const std::string &default_ext) const
|
void PrintBase::update_object_placeholders(DynamicConfig &config, const std::string &default_ext) const
|
||||||
{
|
{
|
||||||
// get the first input file name
|
// get the first input file name
|
||||||
std::string input_file;
|
std::string input_file;
|
||||||
|
std::string first_object_name;
|
||||||
std::vector<std::string> v_scale;
|
std::vector<std::string> v_scale;
|
||||||
int num_objects = 0;
|
int num_objects = 0;
|
||||||
int num_instances = 0;
|
int num_instances = 0;
|
||||||
@@ -38,6 +39,8 @@ void PrintBase::update_object_placeholders(DynamicConfig &config, const std::str
|
|||||||
}
|
}
|
||||||
if (printable) {
|
if (printable) {
|
||||||
++ num_objects;
|
++ num_objects;
|
||||||
|
if (num_objects == 1)
|
||||||
|
first_object_name = model_object->name;
|
||||||
// CHECK_ME -> Is the following correct ?
|
// CHECK_ME -> Is the following correct ?
|
||||||
v_scale.push_back("x:" + boost::lexical_cast<std::string>(printable->get_scaling_factor(X) * 100) +
|
v_scale.push_back("x:" + boost::lexical_cast<std::string>(printable->get_scaling_factor(X) * 100) +
|
||||||
"% y:" + boost::lexical_cast<std::string>(printable->get_scaling_factor(Y) * 100) +
|
"% y:" + boost::lexical_cast<std::string>(printable->get_scaling_factor(Y) * 100) +
|
||||||
@@ -51,6 +54,7 @@ void PrintBase::update_object_placeholders(DynamicConfig &config, const std::str
|
|||||||
config.set_key_value("num_instances", new ConfigOptionInt(num_instances));
|
config.set_key_value("num_instances", new ConfigOptionInt(num_instances));
|
||||||
|
|
||||||
config.set_key_value("scale", new ConfigOptionStrings(v_scale));
|
config.set_key_value("scale", new ConfigOptionStrings(v_scale));
|
||||||
|
config.set_key_value("first_object_name", new ConfigOptionString(first_object_name));
|
||||||
if (! input_file.empty()) {
|
if (! input_file.empty()) {
|
||||||
// get basename with and without suffix
|
// get basename with and without suffix
|
||||||
const std::string input_filename = boost::filesystem::path(input_file).filename().string();
|
const std::string input_filename = boost::filesystem::path(input_file).filename().string();
|
||||||
|
|||||||
@@ -194,6 +194,7 @@ std::string debug_out_path(const char *name, ...);
|
|||||||
// smaller level means less log. level=5 means saving all logs.
|
// smaller level means less log. level=5 means saving all logs.
|
||||||
void set_log_path_and_level(const std::string& file, unsigned int level);
|
void set_log_path_and_level(const std::string& file, unsigned int level);
|
||||||
void flush_logs();
|
void flush_logs();
|
||||||
|
void shutdown_console_logging();
|
||||||
boost::filesystem::path get_log_file_name();
|
boost::filesystem::path get_log_file_name();
|
||||||
|
|
||||||
// A special type for strings encoded in the local Windows 8-bit code page.
|
// A special type for strings encoded in the local Windows 8-bit code page.
|
||||||
|
|||||||
@@ -5,6 +5,7 @@
|
|||||||
#include <locale>
|
#include <locale>
|
||||||
#include <ctime>
|
#include <ctime>
|
||||||
#include <cstdarg>
|
#include <cstdarg>
|
||||||
|
#include <iostream>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <filesystem>
|
#include <filesystem>
|
||||||
|
|
||||||
@@ -46,14 +47,19 @@
|
|||||||
#include <boost/log/core.hpp>
|
#include <boost/log/core.hpp>
|
||||||
#include <boost/log/trivial.hpp>
|
#include <boost/log/trivial.hpp>
|
||||||
#include <boost/log/expressions.hpp>
|
#include <boost/log/expressions.hpp>
|
||||||
|
#include <boost/log/sinks/async_frontend.hpp>
|
||||||
#include <boost/log/sinks/text_file_backend.hpp>
|
#include <boost/log/sinks/text_file_backend.hpp>
|
||||||
|
#include <boost/log/sinks/text_ostream_backend.hpp>
|
||||||
#include <boost/log/utility/setup/file.hpp>
|
#include <boost/log/utility/setup/file.hpp>
|
||||||
#include <boost/log/utility/setup/common_attributes.hpp>
|
#include <boost/log/utility/setup/common_attributes.hpp>
|
||||||
#include <boost/log/sources/severity_logger.hpp>
|
#include <boost/log/sources/severity_logger.hpp>
|
||||||
#include <boost/log/sources/record_ostream.hpp>
|
#include <boost/log/sources/record_ostream.hpp>
|
||||||
#include <boost/log/support/date_time.hpp>
|
#include <boost/log/support/date_time.hpp>
|
||||||
|
|
||||||
|
#include <boost/core/null_deleter.hpp>
|
||||||
#include <boost/locale.hpp>
|
#include <boost/locale.hpp>
|
||||||
|
#include <boost/make_shared.hpp>
|
||||||
|
#include <boost/shared_ptr.hpp>
|
||||||
|
|
||||||
#include <boost/algorithm/string/predicate.hpp>
|
#include <boost/algorithm/string/predicate.hpp>
|
||||||
#include <boost/filesystem.hpp>
|
#include <boost/filesystem.hpp>
|
||||||
@@ -174,6 +180,7 @@ unsigned get_logging_level()
|
|||||||
}
|
}
|
||||||
|
|
||||||
boost::shared_ptr<boost::log::sinks::synchronous_sink<boost::log::sinks::text_file_backend>> g_log_sink;
|
boost::shared_ptr<boost::log::sinks::synchronous_sink<boost::log::sinks::text_file_backend>> g_log_sink;
|
||||||
|
boost::shared_ptr<boost::log::sinks::asynchronous_sink<boost::log::sinks::text_ostream_backend>> g_console_log_sink;
|
||||||
|
|
||||||
// Force set_logging_level(<=error) after loading of the DLL.
|
// Force set_logging_level(<=error) after loading of the DLL.
|
||||||
// This is currently only needed if libslic3r is loaded as a shared library into Perl interpreter
|
// This is currently only needed if libslic3r is loaded as a shared library into Perl interpreter
|
||||||
@@ -346,6 +353,19 @@ namespace src = boost::log::sources;
|
|||||||
namespace expr = boost::log::expressions;
|
namespace expr = boost::log::expressions;
|
||||||
namespace keywords = boost::log::keywords;
|
namespace keywords = boost::log::keywords;
|
||||||
namespace attrs = boost::log::attributes;
|
namespace attrs = boost::log::attributes;
|
||||||
|
namespace sinks = boost::log::sinks;
|
||||||
|
|
||||||
|
void shutdown_console_logging()
|
||||||
|
{
|
||||||
|
if (!g_console_log_sink)
|
||||||
|
return;
|
||||||
|
|
||||||
|
auto console_sink = g_console_log_sink;
|
||||||
|
boost::log::core::get()->remove_sink(console_sink);
|
||||||
|
console_sink->stop();
|
||||||
|
g_console_log_sink.reset();
|
||||||
|
}
|
||||||
|
|
||||||
void set_log_path_and_level(const std::string& file, unsigned int level)
|
void set_log_path_and_level(const std::string& file, unsigned int level)
|
||||||
{
|
{
|
||||||
#ifdef __APPLE__
|
#ifdef __APPLE__
|
||||||
@@ -377,6 +397,24 @@ void set_log_path_and_level(const std::string& file, unsigned int level)
|
|||||||
keywords::auto_flush = true
|
keywords::auto_flush = true
|
||||||
);
|
);
|
||||||
|
|
||||||
|
shutdown_console_logging();
|
||||||
|
|
||||||
|
#ifdef SLIC3R_CONSOLE_LOG
|
||||||
|
auto console_backend = boost::make_shared<sinks::text_ostream_backend>();
|
||||||
|
console_backend->add_stream(boost::shared_ptr<std::ostream>(&std::cout, boost::null_deleter()));
|
||||||
|
console_backend->auto_flush(true);
|
||||||
|
|
||||||
|
g_console_log_sink = boost::make_shared<sinks::asynchronous_sink<sinks::text_ostream_backend>>(console_backend);
|
||||||
|
g_console_log_sink->set_formatter(
|
||||||
|
expr::stream
|
||||||
|
<< "[" << expr::attr< logging::trivial::severity_level >("Severity") << "]\t"
|
||||||
|
<< expr::format_date_time< boost::posix_time::ptime >("TimeStamp", "%Y-%m-%d %H:%M:%S.%f") << " "
|
||||||
|
<<"[Thread " << expr::attr<attrs::current_thread_id::value_type>("ThreadID") << "]"
|
||||||
|
<< ": " << expr::smessage
|
||||||
|
);
|
||||||
|
boost::log::core::get()->add_sink(g_console_log_sink);
|
||||||
|
#endif
|
||||||
|
|
||||||
logging::add_common_attributes();
|
logging::add_common_attributes();
|
||||||
|
|
||||||
set_logging_level(level);
|
set_logging_level(level);
|
||||||
|
|||||||
@@ -1472,8 +1472,32 @@ int GUI_App::install_plugin(std::string name, std::string package_name, InstallP
|
|||||||
boost::filesystem::create_directories(dest_path.parent_path());
|
boost::filesystem::create_directories(dest_path.parent_path());
|
||||||
std::string dest_zip_file = encode_path(dest_path.string().c_str());
|
std::string dest_zip_file = encode_path(dest_path.string().c_str());
|
||||||
try {
|
try {
|
||||||
if (fs::exists(dest_path))
|
if (fs::exists(dest_path)) {
|
||||||
fs::remove(dest_path);
|
boost::system::error_code ec;
|
||||||
|
fs::remove(dest_path, ec);
|
||||||
|
if (ec) {
|
||||||
|
// On Windows a currently-loaded DLL (e.g. BambuSource.dll, or the
|
||||||
|
// networking library in legacy mode) cannot be deleted or overwritten
|
||||||
|
// in place, which failed the whole install with "The plug-in file may
|
||||||
|
// be in use" (issue #14373). It CAN however be renamed aside: the
|
||||||
|
// running module keeps mapping the renamed file while we write the new
|
||||||
|
// one. The stale ".old" copy is cleared on the next install/launch.
|
||||||
|
boost::filesystem::path aside = dest_path;
|
||||||
|
aside += ".old";
|
||||||
|
boost::system::error_code ec2;
|
||||||
|
fs::remove(aside, ec2);
|
||||||
|
fs::rename(dest_path, aside, ec2);
|
||||||
|
if (ec2) {
|
||||||
|
close_zip_reader(&archive);
|
||||||
|
BOOST_LOG_TRIVIAL(error) << "[install_plugin] cannot replace in-use file "
|
||||||
|
<< dest_path.string() << ": " << ec2.message();
|
||||||
|
if (pro_fn) { pro_fn(InstallStatusUnzipFailed, 0, cancel); }
|
||||||
|
return InstallStatusUnzipFailed;
|
||||||
|
}
|
||||||
|
BOOST_LOG_TRIVIAL(warning) << "[install_plugin] " << dest_path.filename().string()
|
||||||
|
<< " was in use, renamed aside to .old";
|
||||||
|
}
|
||||||
|
}
|
||||||
mz_bool res = 0;
|
mz_bool res = 0;
|
||||||
#ifndef WIN32
|
#ifndef WIN32
|
||||||
if (S_ISLNK(stat.m_external_attr >> 16)) {
|
if (S_ISLNK(stat.m_external_attr >> 16)) {
|
||||||
@@ -2259,6 +2283,7 @@ GUI_App::~GUI_App()
|
|||||||
|
|
||||||
|
|
||||||
BOOST_LOG_TRIVIAL(info) << __FUNCTION__<< boost::format(": exit");
|
BOOST_LOG_TRIVIAL(info) << __FUNCTION__<< boost::format(": exit");
|
||||||
|
shutdown_console_logging();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool GUI_App::is_blocking_printing(MachineObject *obj_)
|
bool GUI_App::is_blocking_printing(MachineObject *obj_)
|
||||||
@@ -3473,6 +3498,26 @@ void GUI_App::copy_network_if_available()
|
|||||||
|
|
||||||
bool GUI_App::on_init_network(bool try_backup)
|
bool GUI_App::on_init_network(bool try_backup)
|
||||||
{
|
{
|
||||||
|
// Clean up stale ".old" files left by install_plugin() when it had to rename an in-use
|
||||||
|
// DLL aside (see the rename-aside path in install_plugin). This runs before the plug-in
|
||||||
|
// is (re)loaded - at startup nothing is mapped yet, and on a hot reload the previous
|
||||||
|
// module has already been unloaded - so the previously locked files can now be removed.
|
||||||
|
{
|
||||||
|
boost::filesystem::path plugin_folder = boost::filesystem::path(data_dir()) / "plugins";
|
||||||
|
boost::system::error_code ec;
|
||||||
|
if (boost::filesystem::is_directory(plugin_folder, ec)) {
|
||||||
|
for (boost::filesystem::directory_iterator it(plugin_folder, ec), end; !ec && it != end; it.increment(ec)) {
|
||||||
|
if (it->path().extension() == ".old") {
|
||||||
|
boost::system::error_code rm_ec;
|
||||||
|
boost::filesystem::remove(it->path(), rm_ec);
|
||||||
|
if (rm_ec)
|
||||||
|
BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << ": could not remove stale " << it->path().filename().string()
|
||||||
|
<< " (" << rm_ec.message() << "), will retry next launch";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
auto should_load_networking_plugin = app_config->get_bool("installed_networking");
|
auto should_load_networking_plugin = app_config->get_bool("installed_networking");
|
||||||
|
|
||||||
std::string config_version = app_config->get_network_plugin_version();
|
std::string config_version = app_config->get_network_plugin_version();
|
||||||
|
|||||||
@@ -91,9 +91,14 @@ Vec3d GLGizmoMeasure::get_feature_offset(const Measure::SurfaceFeature &feature)
|
|||||||
}
|
}
|
||||||
case Measure::SurfaceFeatureType::Edge:
|
case Measure::SurfaceFeatureType::Edge:
|
||||||
{
|
{
|
||||||
std::optional<Vec3d> p = feature.get_extra_point();
|
// Only polygon edges store an extra point (the polygon centre); plain edges have none.
|
||||||
assert(p.has_value());
|
const std::optional<Vec3d> extra = feature.get_extra_point();
|
||||||
ret = *p;
|
if (extra.has_value())
|
||||||
|
ret = *extra;
|
||||||
|
else {
|
||||||
|
const auto [pt1, pt2] = feature.get_edge();
|
||||||
|
ret = 0.5 * (pt1 + pt2);
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case Measure::SurfaceFeatureType::Point:
|
case Measure::SurfaceFeatureType::Point:
|
||||||
@@ -1065,7 +1070,7 @@ void GLGizmoMeasure::on_render()
|
|||||||
|
|
||||||
if (requires_raycaster_update) {
|
if (requires_raycaster_update) {
|
||||||
if (m_gripper_id_raycast_map.find(GripperType::SPHERE_2) != m_gripper_id_raycast_map.end()) {
|
if (m_gripper_id_raycast_map.find(GripperType::SPHERE_2) != m_gripper_id_raycast_map.end()) {
|
||||||
m_gripper_id_raycast_map[GripperType::SPHERE_2]->set_transform(Geometry::translation_transform(get_feature_offset(*m_selected_features.first.feature)) *
|
m_gripper_id_raycast_map[GripperType::SPHERE_2]->set_transform(Geometry::translation_transform(get_feature_offset(*m_selected_features.second.feature)) *
|
||||||
Geometry::scale_transform(inv_zoom));
|
Geometry::scale_transform(inv_zoom));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -535,6 +535,9 @@ void Selection::drop()
|
|||||||
|
|
||||||
for (unsigned int i : m_list) {
|
for (unsigned int i : m_list) {
|
||||||
GLVolume& volume = *(*m_volumes)[i];
|
GLVolume& volume = *(*m_volumes)[i];
|
||||||
|
// Skip the wipe tower: its synthetic id (>= 1000) is not an index into m_model->objects.
|
||||||
|
if (volume.object_idx() >= 1000)
|
||||||
|
continue;
|
||||||
ModelObject* model_object = m_model->objects[volume.object_idx()];
|
ModelObject* model_object = m_model->objects[volume.object_idx()];
|
||||||
|
|
||||||
if (model_object != nullptr) {
|
if (model_object != nullptr) {
|
||||||
@@ -1848,6 +1851,9 @@ void Selection::notify_instance_update(int object_idx, int instance_idx)
|
|||||||
for (unsigned int i : m_list)
|
for (unsigned int i : m_list)
|
||||||
{
|
{
|
||||||
int obj_index = (*m_volumes)[i]->object_idx();
|
int obj_index = (*m_volumes)[i]->object_idx();
|
||||||
|
// Skip the wipe tower: its synthetic id (>= 1000) is not an index into m_model->objects.
|
||||||
|
if (obj_index >= 1000)
|
||||||
|
continue;
|
||||||
//-1 means all the instance in this object
|
//-1 means all the instance in this object
|
||||||
if (instance_idx == -1)
|
if (instance_idx == -1)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -183,6 +183,74 @@ void trigger_precise_wall_warning(DynamicPrintConfig& c)
|
|||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
|
// ---------------------------------------------------------------------------
|
||||||
|
// {first_object_name} filename placeholder
|
||||||
|
// ---------------------------------------------------------------------------
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
// Add a printable 20mm cube named `name` to `model`; returns it so the caller can tweak it.
|
||||||
|
ModelObject* add_named_cube(Model& model, const std::string& name)
|
||||||
|
{
|
||||||
|
ModelObject* obj = model.add_object();
|
||||||
|
obj->name = name;
|
||||||
|
obj->add_volume(make_cube(20.0, 20.0, 20.0));
|
||||||
|
obj->add_instance();
|
||||||
|
obj->ensure_on_bed();
|
||||||
|
return obj;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Resolve `format` to an output file name for a print of `model`. `filename_base`, when set,
|
||||||
|
// is the saved-project name passed to output_filename().
|
||||||
|
std::string resolved_output_name(Model& model, const std::string& format, const std::string& filename_base = {})
|
||||||
|
{
|
||||||
|
DynamicPrintConfig config = DynamicPrintConfig::full_print_config();
|
||||||
|
config.set_key_value("filename_format", new ConfigOptionString(format));
|
||||||
|
|
||||||
|
Print print;
|
||||||
|
for (ModelObject* obj : model.objects)
|
||||||
|
print.auto_assign_extruders(obj);
|
||||||
|
print.apply(model, config);
|
||||||
|
return print.output_filename(filename_base);
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace
|
||||||
|
|
||||||
|
TEST_CASE("Print: {first_object_name} names the first printable object on the plate", "[Print]")
|
||||||
|
{
|
||||||
|
Model model;
|
||||||
|
|
||||||
|
SECTION("uses the object's name") {
|
||||||
|
add_named_cube(model, "WidgetPart");
|
||||||
|
CHECK(resolved_output_name(model, "{first_object_name}") == "WidgetPart.gcode");
|
||||||
|
}
|
||||||
|
|
||||||
|
SECTION("picks the first when several objects are printable") {
|
||||||
|
add_named_cube(model, "FirstPart");
|
||||||
|
add_named_cube(model, "SecondPart");
|
||||||
|
CHECK(resolved_output_name(model, "{first_object_name}") == "FirstPart.gcode");
|
||||||
|
}
|
||||||
|
|
||||||
|
SECTION("skips objects outside the print volume (e.g. on another plate)") {
|
||||||
|
// First in model order, but not on the current plate, so is_printable() is false.
|
||||||
|
add_named_cube(model, "OtherPlatePart")->instances.front()->print_volume_state = ModelInstancePVS_Fully_Outside;
|
||||||
|
add_named_cube(model, "OnPlatePart");
|
||||||
|
CHECK(resolved_output_name(model, "{first_object_name}") == "OnPlatePart.gcode");
|
||||||
|
}
|
||||||
|
|
||||||
|
SECTION("is empty when the object has no name") {
|
||||||
|
add_named_cube(model, "");
|
||||||
|
CHECK(resolved_output_name(model, "part_{first_object_name}") == "part_.gcode");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_CASE("Print: {first_object_name} is not replaced by the saved-project file name", "[Print]")
|
||||||
|
{
|
||||||
|
// Passing a saved-project file name as the filename_base must not change {first_object_name}.
|
||||||
|
Model model;
|
||||||
|
add_named_cube(model, "WidgetPart");
|
||||||
|
CHECK(resolved_output_name(model, "{first_object_name}", "SavedProject") == "WidgetPart.gcode");
|
||||||
|
}
|
||||||
|
|
||||||
TEST_CASE("Print::validate stacks independent warnings", "[Print][validate]")
|
TEST_CASE("Print::validate stacks independent warnings", "[Print][validate]")
|
||||||
{
|
{
|
||||||
// Two unrelated checks (region precise-wall + machine acceleration) must each
|
// Two unrelated checks (region precise-wall + machine acceleration) must each
|
||||||
|
|||||||
@@ -11,8 +11,8 @@ SCENARIO("Placeholder parser scripting", "[PlaceholderParser]") {
|
|||||||
|
|
||||||
config.set_deserialize_strict( {
|
config.set_deserialize_strict( {
|
||||||
{ "printer_notes", " PRINTER_VENDOR_PRUSA3D PRINTER_MODEL_MK2 " },
|
{ "printer_notes", " PRINTER_VENDOR_PRUSA3D PRINTER_MODEL_MK2 " },
|
||||||
{ "nozzle_diameter", "0.6;0.6;0.6;0.6" },
|
{ "nozzle_diameter", "0.6,0.6,0.6,0.6" },
|
||||||
{ "nozzle_temperature", "357;359;363;378" }
|
{ "nozzle_temperature", "357,359,363,378" }
|
||||||
});
|
});
|
||||||
// To test the "min_width_top_surface" over "inner_wall_line_width".
|
// To test the "min_width_top_surface" over "inner_wall_line_width".
|
||||||
config.option<ConfigOptionFloatOrPercent>("inner_wall_line_width")->value = 150.;
|
config.option<ConfigOptionFloatOrPercent>("inner_wall_line_width")->value = 150.;
|
||||||
@@ -121,8 +121,8 @@ SCENARIO("Placeholder parser variables", "[PlaceholderParser]") {
|
|||||||
config.set_deserialize_strict({
|
config.set_deserialize_strict({
|
||||||
{ "filament_notes", "testnotes" },
|
{ "filament_notes", "testnotes" },
|
||||||
{ "enable_pressure_advance", "1" },
|
{ "enable_pressure_advance", "1" },
|
||||||
{ "nozzle_diameter", "0.6;0.6;0.6;0.6" },
|
{ "nozzle_diameter", "0.6,0.6,0.6,0.6" },
|
||||||
{ "nozzle_temperature", "357;359;363;378" }
|
{ "nozzle_temperature", "357,359,363,378" }
|
||||||
});
|
});
|
||||||
|
|
||||||
PlaceholderParser::ContextData context_with_global_dict;
|
PlaceholderParser::ContextData context_with_global_dict;
|
||||||
@@ -241,3 +241,97 @@ SCENARIO("Placeholder parser variables", "[PlaceholderParser]") {
|
|||||||
}
|
}
|
||||||
SECTION("if else completely empty") { REQUIRE(parser.process("{if false then elsif false then else endif}", 0, nullptr, nullptr, nullptr) == ""); }
|
SECTION("if else completely empty") { REQUIRE(parser.process("{if false then elsif false then else endif}", 0, nullptr, nullptr, nullptr) == ""); }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SCENARIO("Placeholder parser coFloatsOrPercents vector access", "[PlaceholderParser]") {
|
||||||
|
PlaceholderParser parser;
|
||||||
|
auto config = DynamicPrintConfig::full_print_config();
|
||||||
|
|
||||||
|
// outer_wall_speed is the ratio_over target for small_perimeter_speed.
|
||||||
|
// Different values per extruder to verify parent resolves at the same element index.
|
||||||
|
config.set_deserialize_strict({
|
||||||
|
{ "outer_wall_speed", "60,70,80,90" },
|
||||||
|
{ "nozzle_diameter", "0.4,0.4,0.4,0.4" },
|
||||||
|
{ "pressure_advance", "1.5,2.0,3.0,4.0" } // coFloats non-nullable
|
||||||
|
});
|
||||||
|
// small_perimeter_speed:
|
||||||
|
// [0] = 50% of outer_wall_speed[0] (= 60) → 30
|
||||||
|
// [1] = 80% of outer_wall_speed[1] (= 70) → 56
|
||||||
|
// [2] = 0 absolute
|
||||||
|
// [3] = 50% of outer_wall_speed[3] (= 90) → 45
|
||||||
|
config.option<ConfigOptionFloatsOrPercentsNullable>("small_perimeter_speed")->values = {
|
||||||
|
FloatOrPercent{50.0, true}, // 50% of outer_wall_speed[0] (60) = 30
|
||||||
|
FloatOrPercent{80.0, true}, // 80% of outer_wall_speed[1] (70) = 56
|
||||||
|
FloatOrPercent{0.0, false}, // absolute: 0
|
||||||
|
FloatOrPercent{50.0, true}, // 50% of outer_wall_speed[3] (90) = 45
|
||||||
|
};
|
||||||
|
|
||||||
|
parser.apply_config(config);
|
||||||
|
parser.set("foo", 0);
|
||||||
|
parser.set("bar", 1);
|
||||||
|
parser.set("baz", 3);
|
||||||
|
parser.set("num_extruders", 4);
|
||||||
|
|
||||||
|
SECTION("Indexed access - percent resolved against parent at same index [0]") {
|
||||||
|
// 50% of outer_wall_speed[0] (60) = 30
|
||||||
|
REQUIRE(std::stod(parser.process("{small_perimeter_speed[0]}")) == Catch::Approx(30.0));
|
||||||
|
}
|
||||||
|
|
||||||
|
SECTION("Indexed access - percent resolved against parent at same index [1]") {
|
||||||
|
// 80% of outer_wall_speed[1] (70) = 56
|
||||||
|
REQUIRE(std::stod(parser.process("{small_perimeter_speed[1]}")) == Catch::Approx(56.0));
|
||||||
|
}
|
||||||
|
|
||||||
|
SECTION("Indexed access - percent resolved against parent at same index [3]") {
|
||||||
|
// 50% of outer_wall_speed[3] (90) = 45
|
||||||
|
REQUIRE(std::stod(parser.process("{small_perimeter_speed[3]}")) == Catch::Approx(45.0));
|
||||||
|
}
|
||||||
|
|
||||||
|
SECTION("Variable-indexed access via foo (=0) - percent value") {
|
||||||
|
// 50% of outer_wall_speed[0] (60) = 30
|
||||||
|
REQUIRE(std::stod(parser.process("{small_perimeter_speed[foo]}")) == Catch::Approx(30.0));
|
||||||
|
}
|
||||||
|
|
||||||
|
SECTION("Variable-indexed access via bar (=1) - percent value") {
|
||||||
|
// 80% of outer_wall_speed[1] (70) = 56
|
||||||
|
REQUIRE(std::stod(parser.process("{small_perimeter_speed[bar]}")) == Catch::Approx(56.0));
|
||||||
|
}
|
||||||
|
|
||||||
|
SECTION("Variable-indexed access via baz (=3) - percent value") {
|
||||||
|
// 50% of outer_wall_speed[3] (90) = 45
|
||||||
|
REQUIRE(std::stod(parser.process("{small_perimeter_speed[baz]}")) == Catch::Approx(45.0));
|
||||||
|
}
|
||||||
|
|
||||||
|
SECTION("Literal-indexed access - absolute value") {
|
||||||
|
REQUIRE(std::stod(parser.process("{small_perimeter_speed[2]}")) == Catch::Approx(0.0));
|
||||||
|
}
|
||||||
|
|
||||||
|
SECTION("No-index (extruder-based) access - percent resolved via current extruder") {
|
||||||
|
// Extruder 0 = 50% of outer_wall_speed[0] (60) = 30
|
||||||
|
REQUIRE(std::stod(parser.process("{small_perimeter_speed}")) == Catch::Approx(30.0));
|
||||||
|
}
|
||||||
|
|
||||||
|
SECTION("Out-of-range index clamps to index 0") {
|
||||||
|
// Index 99 is out of range, clamps to 0: 50% of outer_wall_speed[0] (60) = 30
|
||||||
|
REQUIRE(std::stod(parser.process("{small_perimeter_speed[99]}")) == Catch::Approx(30.0));
|
||||||
|
}
|
||||||
|
|
||||||
|
SECTION("coFloats no-index access - nullable (outer_wall_speed)") {
|
||||||
|
// outer_wall_speed is ConfigOptionFloatsNullable, exercises the 'if' branch
|
||||||
|
REQUIRE(std::stod(parser.process("{outer_wall_speed}")) == Catch::Approx(60.0));
|
||||||
|
}
|
||||||
|
|
||||||
|
SECTION("coFloats indexed access - nullable") {
|
||||||
|
// outer_wall_speed[2] = 80
|
||||||
|
REQUIRE(std::stod(parser.process("{outer_wall_speed[2]}")) == Catch::Approx(80.0));
|
||||||
|
}
|
||||||
|
|
||||||
|
SECTION("coFloats no-index access - non-nullable (pressure_advance)") {
|
||||||
|
// pressure_advance is ConfigOptionFloats (non-nullable), exercises the 'else' branch
|
||||||
|
REQUIRE(std::stod(parser.process("{pressure_advance}")) == Catch::Approx(1.5));
|
||||||
|
}
|
||||||
|
|
||||||
|
SECTION("coFloats indexed access - non-nullable") {
|
||||||
|
// pressure_advance[2] = 3.0
|
||||||
|
REQUIRE(std::stod(parser.process("{pressure_advance[2]}")) == Catch::Approx(3.0));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user